synchronized(class reference)是什么意思?

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

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

@Chandana - 不正确。 - Hot Licks
4个回答

6
它进入监视器以获取Foo.class对象。如果另一个方法也在Foo.Class上同步,它将不得不等待,假设它在另一个线程中。
如果一个方法没有同步,那么它将不受影响,无论它是否是静态的。请注意,同步静态方法隐式地在定义它们的类的类对象上进行同步。

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 中是右括号}的结尾)。

0

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

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

同步不会对字段产生任何影响 - 没有办法声明一个同步字段。


-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

在任务1持有实例锁的同时,任务2更新valueB,我认为这表明静态锁并不能锁定类的所有实例。


它不会锁定任何成员或任何东西。它根本不会锁定任何东西。它在类对象上进行同步 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接