成员方法在全班同步

Rad*_*ium 0 java synchronized

经过一番快速搜索,我无法找到明确的答案.

是否有一些更优雅的方法来同步整个类的整个成员方法(绑定在实例上)?这意味着可以通过多个线程在多个实例上调用方法,但是当时只能由一个线程调用.它也可以写为同步块.

(例如,该方法将其实例插入共享缓存中.)

class DataObject {

  public putInCache() {
    synchronized(getClass()) {

      // ... do some stuff
      cache.insert(this);
      // ... do some more stuff

    }
  }

}
Run Code Online (Sandbox Code Playgroud)

Joa*_*uer 6

避免在可公开访问的对象上进行同步是个好主意.但是,您可以使用共享监视器对象:

class DataObject {

  private static final Object cacheLock = new Object();

  public putInCache() {
    synchronized(cacheLock) {

      // ... do some stuff
      cache.insert(this);
      // ... do some more stuff

    }
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,使用此特定实现DataObject,从其派生的所有类将共享锁.


Bor*_*der 5

Classinstance同步之间存在差异.
实例同步适用于每个实例Object,因此代码:

  public synchronized void putInCache() {
      // ... do some stuff
      cache.insert(this);
      // ... do some more stuff
  }
Run Code Online (Sandbox Code Playgroud)

和代码

  public void putInCache() {
    synchronized(this) {
      // ... do some stuff
      cache.insert(this);
      // ... do some more stuff
    }
  }
Run Code Online (Sandbox Code Playgroud)

相当于它们不允许多个线程同时进入同步块; 但是这仅适用于课程中的每个实例.即显示器已打开this

类同步适用于Class自身,以下两个块也是等效的:

  public static synchronized void putInCache() {
      // ... do some stuff
      cache.insert(this);
      // ... do some more stuff
  }
  public void putInCache() {
    synchronized(MyClass.class) {
      // ... do some stuff
      cache.insert(this);
      // ... do some more stuff
    }
  }
Run Code Online (Sandbox Code Playgroud)

它们不允许多个线程同时在JVM上同时进入同步块,即监视器位于Class实例上且非常独特.

您需要使用Class同步.

另一种方法是锁定资源本身,因为这是您试图阻止并发访问的内容; 如果资源不能为null,并且资源的实例不会随机更改 - 如果final您可以执行此操作,则更好:

 public void putInCache() {
    synchronized(cache) {
      // ... do some stuff
      cache.insert(this);
      // ... do some more stuff
    }
  }
Run Code Online (Sandbox Code Playgroud)

这清楚地说明了为什么要锁定以及锁定什么.