synchronized(Foo.Class){
//some code..
}
这会锁定 Foo 类的所有实例还是仅锁定静态方法/字段?
synchronized(Foo.Class){
//some code..
}
这会锁定 Foo 类的所有实例还是仅锁定静态方法/字段?
它进入Foo.class
对象的监视器。如果另一个方法也同步Foo.Class
,它必须等待,假设它在不同的线程中。
如果一个方法没有对其进行同步,那么无论它是否是静态的,它都不会受到影响。并不是说同步静态方法隐式地在定义它们的类的类对象上同步。
类对象的同步与实例的同步完全一样。诸如此类的类Foo.class
是一个对象,因此具有内置监视器。您提供的代码:
synchronized(Foo.Class){
//some code..
}
同步对 Foo 类的访问。它在尝试同步类的静态变量时很有用。例如:
public class Foo{
private static int COUNTER = 0;
synchronized public static void increment(){
COUNTER ++;
}
public static void decrement(){
synchronized (Foo.class) {
COUNTER ++;
}
}
}
如您所见,Foo.class
可以与任何实例一样实现同步。当尝试同步实例的代码块时,synchronized(this){}
使用 : 相当于synchronized(Foo.class){}
类对象的情况。这同样适用于同步方法: synchronized public void increment(){}
相当于:synchronized public static void increment(){}
现在关于你的问题:
这会锁定 Foo 类的所有实例还是仅锁定它的静态方法/字段?
当然,它不会像上面解释的那样获取所有实例的锁。此外,类对象不知道创建的实例。synchronized
块不锁定字段。它只锁定一个代码/方法块,该代码块被获取该锁的线程强制作为原子操作执行,并且没有其他线程可以进入该代码块(但如果它们不同步,则可以执行其他块),直到第一个线程释放锁(在 Java 中是大括号的结尾}
)。
它同步对使用它的方法/同步子句的访问。这些可以是 Bar 类的方法——不一定是 Foo。
重要的是,在“Foo.class”上同步的所有方法/同步子句都相互排除在同时执行之外。
同步根本不影响字段——没有办法声明字段同步。
我对本教程 synchronized(Foo.class) {...}
的解释将只锁定类的静态成员。但要确保你需要编写一个测试。
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");
}
}
这给出了输出:
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
当任务 2 更新valueB
而任务 1 持有实例锁时,我认为这表明静态锁不会锁定类的所有实例。