0

以下程序在静态同步方法和实例同步方法试图访问不同线程中同一类的静态字段的情况下会发生什么行为?任何线程都会被阻塞吗?它非常混乱。

class MyClass
{
        public static int i = 5;

        public synchronized void m1()
        {
                System.out.println(i); //uses static field i of MyClass
            //T1 is executing this method
        }

        public static synchronized void m3()
        {
            //T2 will be able to call this method on same object lock while it is using
            //static field i???
            System.out.println(i);//uses static field i of MyClass
        }
}
4

5 回答 5

6

同步实例方法等价于

public void m1() {
    synchronized(this) {
        ...
    }
}

(好吧,它们并不完全相同,但是您的问题的答案不会受到这种差异的影响)。

同步的静态方法在类上同步:

public void m2() {
    synchronized(MyClass.class) {
        ...
    }
}

如您所见,两个块在不同的对象m1上同步:在调用它的实例上m2同步,在Class<MyClass>代表您在 JVM 中的类的实例上同步。所以这两个方法可以在不相互阻塞的情况下调用。

于 2013-03-06T14:48:34.640 回答
4

你总是在一个对象上同步。

函数 m1 在调用它的对象的实例上同步。

函数 m3 在类本身上同步。

m1 可以写成:

        public void m1()
        {
            synchronized(this) { 
                System.out.println(i); //uses static field i of MyClass
                //T1 is executing this method
            }
        }

因此,您正在对两个不同的对象进行同步,这两种方法可以同时访问任何全局变量。

于 2013-03-06T14:43:00.937 回答
1

您的示例代码看起来不错。

根据我的说法,确保静态变量同步的最佳方法是。由于在您的班级之外无法访问锁定对象。见下文。

public class MyClass
{
    private static int i = 0;
    private static final Object lockObject = new Object();

    public void m1() {
        synchronized (lockObject ) {
            //Use you static var
        }
    }

    public void m3() {
        synchronized (lockObject ) {
            //Use you static var
        }
    }
} 
于 2013-03-06T14:47:43.133 回答
0

方法 m1 和 m3 可以独立执行。

因为正如你已经说过的那样static synchronized是在对象上。因此与 相同synchronize(MyClass.class)

synchronized在实例范围内可用。所以它只对实例被阻止。这与使用相同:

MyClass myClass = new MyClass();
synchronize (myClass)
{
.....
}
于 2013-03-06T14:44:18.363 回答
-1

Java 没有任何与访问静态字段相关的同步控制。

如果您将方法设为空,则同步将完全相同。

具体来说,只要任何线程正在执行该类型中的任何同步静态方法,所有其他调用同步静态方法的线程都会等待它们完成,因此一次最多会执行一个同步静态方法。

于 2013-03-06T14:41:30.203 回答