public class ObjectCounter {
private static long numOfInstances = 0;
public ObjectCounter(){
synchronized(this){
numOfInstances++;
}
}
**public static synchronized long getCount(){
return numOfInstances;
}**
//vs//
**public static long getCount(){
return numOfInstances;
}**
}
if I'll run few threads, some of them call the static function getCount()
and some of them create new instances. I want to get in each call to getCount()
the real number of instances at the time.
this
" shouldn't it mean that I can't call getCount()
until the constructor exits the synchronized block (lets say if I don't write synchronize on the getCount()).this
" code?`
All synchronized blocks synchronize on the same object can only have one thread executing inside them at a time. All other threads attempting to enter the synchronized block are blocked until the thread inside the synchronized block exits the block.
Object level lock vs class level lock – Important notes. Synchronization in Java guarantees that no two threads can execute a synchronized method, which requires same lock, simultaneously or concurrently. synchronized keyword can be used only with methods and code blocks.
Locks In Synchronized MethodsWhen a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method's object and releases it when the method returns. The lock release occurs even if the return was caused by an uncaught exception.
Synchronized static methods are synchronized on the class object of the class the synchronized static method belongs to. Since only one class object exists in the Java VM per class, only one thread can execute inside a static synchronized method in the same class.
A method with synchronized keyword allows only one thread at a time to let its task complete. A thread that comes first would take the lock and perform its time, meanwhile other thread would wait for first thread to complete its task. A Block with synchronized keyword allows only one thread at a time to let its task complete.
In Java, a Synchronized block helps in performing synchronization on any particular resource of the function or method. If there are 100 lines of code (LOC) and synchronization has to be done for only 10 lines, then a synchronized block can be used. Synchronized can be used as keyword, method and blocks.
And to make it easier for programmers, Java provides the synchronized keyword that operates on the default lock of a class. This default lock is called intrinsic lock which belongs to every Java object. The synchronized keyword can be used at method level or code block level. Let’s look at the first approach first. 1. Synchronized Methods
For synchronized blocks, you can use any non-null object as a lock: synchronized (mymap) { mymap.put(..., ...); } For synchronized methods, the lock will be held throughout the method scope, while in the synchronized block, the lock is held only during that block scope (otherwise known as critical section).
Using synchronized
means in order for a thread to execute that block or method, it has to acquire a lock referenced (explicitly or implicitly) by that block or method. For the static synchronized
methods, that lock is the monitor on the class object. For the synchronized(this)
block, the lock used is the monitor on the current instance. Sharing of locks between multiple methods or blocks is what enforces atomicity and memory visibility of updates, also the shared lock provides a shared communication path through which waiting and notification can take place.
Since the static synchronized blocks use a different lock from that used by the block in the constructor, entering a static synchronized block is not blocked by another thread's accessing the block that requires acquiring the lock on the current instance, and the synchronized block in the constructor has no effect on anything, the lock acquisition will always be uncontended. More importantly here, changes made by one thread in the constructor may not get seen by other threads using the getter. Synchronization affects both locking and memory visibility.
This changed version would work:
public class ObjectCounter {
private static long numOfInstances = 0;
public ObjectCounter(){
synchronized(ObjectCounter.class){
numOfInstances++;
}
}
public static synchronized long getCount(){
return numOfInstances;
}
}
because the getter and the incrementing block are using the same lock. Making the different threads acquire the same monitor ensures that the change to the counter gets safely published so that another thread accessing the getter can see the updated value.
The synchronized keyword says, "you have to acquire a lock before you can enter", where for the method the lock is assumed: with the static keyword on the method it's the monitor on the class, without a static keyword it's the monitor on the current instance. For locking to work correctly the different blocks and methods need to use the same lock. There is arguably too much syntax sugar and too much making things convenient in how Java was designed: allowing implicit choice of locks and putting the monitor on java.lang.Object can cause confusion.
WRT your question #6: For what you're doing here you'd be better off with an AtomicLong. Use synchronized blocks for coordinating multiple changes that need to take place without interference from other threads.
Questions #3, #7 and #8 seem very similar: If a method/block isn't attempting to acquire a lock, nothing prevents threads from executing that method/block. The object as a whole doesn't get any protection, using the synchronized methods or blocks to enforce locking is what does the protecting. Think less in terms of "using the synchronized
keyword" and more in terms of what lock threads need to acquire.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With