2013-03-06 110 views
0

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

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 
     } 
} 

回答

5

同步实例方法是等效的

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

(当然,他们是不完全一样,但回答你的问题并没有从差异苦)。

同步静态方法是在类同步:

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

正如你所看到的,二块上的区别同步的对象:m1是在实例它被称为上保持同步,并m2上同步代表您在JVM中的类的Class<MyClass>的实例。所以这两个方法可以被调用而不会相互阻塞。

-1

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

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

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

+0

不确定你的意思,但Java确实支持静态同步方法:它在类的Class对象上同步。 – 2013-03-06 14:44:04

+0

马克是正确的 – Jazzepi 2013-03-06 15:02:29

+0

@MarkRotteveel:这正是我的意思。它与静态_fields_无关。 – SLaks 2013-03-06 15:10:14

4

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

功能m1在其被调用的对象的实例上进行同步。

函数m3在类本身上进行同步。

M1可以写成:

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

因此要同步两个不同对象上这两种方法可以同时存取权限的任何全局变量。

0

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

因为正如你所说的static synchronized是对象。因此与synchronize(MyClass.class)相同。

​​是实例可用的。所以它只是被阻止的实例。这将与使用相同:

MyClass myClass = new MyClass(); 
synchronize (myClass) 
{ 
..... 
} 
0

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

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

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 
     } 
    } 
}