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

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

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

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

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

既然我们已经定义了一个静态对象,并且我们正在使用该锁的关键字,那么静态变量现在在类的实例之间同步,这是真的吗?locksynchronizedcountTest


答案 1

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

  1. 使用同步静态方法。这将在类对象上进行同步。

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

    public class Test {
        private static int count = 0;
    
        public void incrementCount() {
            synchronized (Test.class) {
                count++;
            }
        }
    } 
    
  3. 在某个其他静态对象上进行同步。

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

在许多情况下,方法 3 是最好的,因为锁对象不会在类外部公开。


答案 2

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

public class Test {

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

    public void foo() {  
        count.incrementAndGet();
    }  
}