如何在Java中运行不同类实例的线程之间同步静态变量?

Ano*_*ous 119 java multithreading synchronization class object

我知道synchronize在方法之前使用关键字会为该对象带来同步.也就是说,将同步运行相同对象实例的2个线程.

但是,由于同步是在对象级别,因此将不会同步运行该对象的不同实例的2个线程.如果我们在由该方法调用的Java类中有一个静态变量,我们希望它在该类的实例之间进行同步.这两个实例在两个不同的线程中运行.

我们可以通过以下方式实现同​​步吗?

public class Test  
{  
   private static int count = 0;  
   private static final Object lock= new Object();    
   public synchronized void foo() 
  {  
      synchronized(lock)
     {  
         count++;  
     }  
  }  
}
Run Code Online (Sandbox Code Playgroud)

是不是因为我们已经定义了一个lock静态的对象并且我们正在使用该synchronized锁的关键字,所以静态变量count现在在类的实例之间同步Test

Dar*_*ron 191

有几种方法可以同步对静态变量的访问.

  1. 使用同步静态方法.这会在类对象上同步.

    public class Test {
        private static int count = 0;
    
        public static synchronized void incrementCount() {
            count++;
        }
    } 
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在类对象上显式同步.

    public class Test {
        private static int count = 0;
    
        public void incrementCount() {
            synchronized (Test.class) {
                count++;
            }
        }
    } 
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在其他一些静态对象上同步.

    public class Test {
        private static int count = 0;
        private static final Object countLock = new Object();
    
        public void incrementCount() {
            synchronized (countLock) {
                count++;
            }
        }
    } 
    
    Run Code Online (Sandbox Code Playgroud)

方法3在许多情况下是最好的,因为锁定对象不会暴露在您的类之外.

  • #3最好的原因是任何随机的代码都可能在`Test.class`上同步并可能破坏你的一天.此外,类初始化运行时会锁定所持有的类,因此如果您有疯狂的类初始化程序,您可能会让自己头痛.`volatile`对`count ++`没有帮助,因为它是一个读/修改/写序列.正如另一个答案所述,`java.util.concurrent.atomic.AtomicInteger`可能是正确的选择. (9认同)
  • 2.声明计数为volatile也可以,因为volatile确保变量是同步的. (4认同)
  • 如果要读取其他线程设置的正确值,请不要忘记在计数时同步读取操作.声明它不稳定(除了同步写入)也将有助于此. (4认同)

Kev*_*vin 64

如果您只是共享一个计数器,请考虑使用AtomicInteger或java.util.concurrent.atomic包中的其他合适的类:

public class Test {

    private final static AtomicInteger count = new AtomicInteger(0); 

    public void foo() {  
        count.incrementAndGet();
    }  
}
Run Code Online (Sandbox Code Playgroud)

  • 它在java 1.5中提供,而不是在1.6中. (3认同)