synchronized(类引用)有什么作用?

时间:2013-03-31 13:53:47

标签: java concurrency static synchronized

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

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

4 个答案:

答案 0 :(得分:6)

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

如果方法没有同步,那么它将不受影响,无论它是否是静态的。并非同步的静态方法在定义它们的类的类对象上隐式同步。

答案 1 :(得分: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中是大括号的结尾 } )。

答案 2 :(得分:0)

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

重要的是,所有在“Foo.class”上同步的方法/ synchronized子句都会被同时执行。

同步根本不会影响字段 - 无法声明字段已同步。

答案 3 :(得分:-1)

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