Reputation: 289
synchronized(Foo.Class){
//some code..
}
Does this lock all the instances of Foo class or only it's static methods/fields?
Upvotes: 4
Views: 200
Reputation: 2840
The synchronization of a class object works exactly as the synchronization of an instance. A class such as Foo.class
is an object and therefore has a built-in monitor. The code that you provided:
synchronized(Foo.Class){
//some code..
}
synchronizes the access to Foo class. It can be useful when attempting to synchronize static variables of a class. For example:
public class Foo{
private static int COUNTER = 0;
synchronized public static void increment(){
COUNTER ++;
}
public static void decrement(){
synchronized (Foo.class) {
COUNTER ++;
}
}
}
As you can see the synchronization of Foo.class
can be achieved identically as for any instance. When attempting to synchronize a code block of an instance the : synchronized(this){}
is used which is equivalent of synchronized(Foo.class){}
in case of a class object. The same applies in case of synchronized methods: synchronized public void increment(){}
is equivalent to: synchronized public static void increment(){}
Now regarding your question:
Does this locks all the instances of Foo class or only it's static methods/fields?
Of course it does not acquire locks of all instances as explained above. Moreover, the class object is not aware of created instances. A synchronized
block does not lock a field. It locks only a block of code/method which is forced to be executed as an atomic operation by the thread that acquired that lock and no other thread can enter that block of code (but can execute other blocks if they are not synchronized) until the first thread releases the lock (which in Java is the end of the curly bracket }
).
Upvotes: 1
Reputation: 1188
My interpretation of the tutorial synchronized(Foo.class) {...}
will lock only the static members of the class. But to be sure you'll need to write a test.
public class SyncTest {
public static SyncTest instance;
public static String valueA;
public String valueB;
public static void main(String[] args) {
instance = new SyncTest();
(new Thread(new Task1())).start();
(new Thread(new Task2())).start();
try {
Thread.sleep(10000);
synchronized(SyncTest.class) {
System.out.println("Value A: " + valueA);
}
synchronized(instance) {
System.out.println("Value B: " + instance.valueB);
}
} catch (InterruptedException interrupt) { }
}
}
class Task1 implements Runnable {
public void run() {
try {
synchronized(SyncTest.class) {
System.out.println("Task 1 Sleeping ");
Thread.sleep(500);
SyncTest.valueA = "One";
System.out.println("T1 A: " + SyncTest.valueA);
}
synchronized(SyncTest.instance) {
Thread.sleep(1000);
SyncTest.instance.valueB = "Two";
System.out.println("T1 B: " + SyncTest.instance.valueB);
}
} catch (InterruptedException interrupt) { }
System.out.println("Task 1 Finished ");
}
}
class Task2 implements Runnable {
public void run() {
System.out.println("Task 2 Started");
try {
Thread.sleep(1000);
synchronized(SyncTest.class) {
SyncTest.instance.valueB = "Four";
System.out.println("T2 B: " + SyncTest.instance.valueB);
Thread.sleep(5000);
SyncTest.valueA = "Three";
System.out.println("T2 A: " + SyncTest.valueA);
}
} catch (InterruptedException interrupt) { }
System.out.println("Task 2 Finished");
}
}
Which gives the output:
Task 1 Sleeping
Task 2 Started
T1 A: One
T2 B: Four
T1 B: Two
Task 1 Finished
T2 A: Three
Task 2 Finished
Value A: Three
Value B: Two
As task 2 update valueB
while task 1 is holding instance lock I think this shows that a static lock does not lock all instances of the class.
Upvotes: -1
Reputation: 47699
It synchronizes access to the methods/synchronized clauses that use it. These could be methods of class Bar -- doesn't have to be Foo.
The important thing is that all methods/synchronized clauses that synchronize on "Foo.class" are mutually excluded from executing simultaneously.
Synchronization does not affect fields at all -- there's no way to declare a field synchronized.
Upvotes: 0
Reputation: 39451
It enters the monitor for the Foo.class
object. If another method synchronizes on Foo.Class
as well, it will have to wait, assuming it's in a different thread.
If a method doesn't synchronize on it, then it will be unaffected, regardless of whether it is static or not. Not that synchronized static methods implicitly synchronize on the class object for the class where they were defined.
Upvotes: 6