【问题标题】:Java synchronized and static synchronized method accessing static fieldJava同步和静态同步方法访问静态字段
【发布时间】:2013-03-06 14:39:48
【问题描述】:

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

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

【问题讨论】:

    标签: java synchronization


    【解决方案1】:

    同步实例方法等价于

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

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

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

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

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

    【讨论】:

      【解决方案2】:

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

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

      函数 m3 在类本身上同步。

      m1 可以写成:

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

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

      【讨论】:

        【解决方案3】:

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

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

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

        【讨论】:

          【解决方案4】:

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

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

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

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

          【讨论】:

            【解决方案5】:

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

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

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

            【讨论】:

            • 不确定您的意思,但 Java 确实支持静态同步方法:它在类的 Class-object 上同步。
            • @MarkRotteveel:这正是我的意思。它与静态 fields 无关。
            猜你喜欢
            • 1970-01-01
            • 2016-09-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多