4
synchronized(Foo.Class){
   //some code..
}

这会锁定 Foo 类的所有实例还是仅锁定静态方法/字段?

4

4 回答 4

6

它进入Foo.class对象的监视器。如果另一个方法也同步Foo.Class,它必须等待,假设它在不同的线程中。

如果一个方法没有对其进行同步,那么无论它是否是静态的,它都不会受到影响。并不是说同步静态方法隐式地在定义它们的类的类对象上同步。

于 2013-03-31T13:58:32.130 回答
1

类对象的同步与实例的同步完全一样。诸如此类的类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 中是大括号的结尾})。

于 2014-09-12T13:25:51.113 回答
0

它同步对使用它的方法/同步子句的访问。这些可以是 Bar 类的方法——不一定是 Foo。

重要的是,在“Foo.class”上同步的所有方法/同步子句都相互排除在同时执行之外。

同步根本不影响字段——没有办法声明字段同步。

于 2013-03-31T14:06:36.120 回答
-1

我对本教程 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 持有实例锁时,我认为这表明静态锁不会锁定类的所有实例。

于 2013-03-31T14:13:09.853 回答