0

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

有没有更优雅的方法来同步整个类的整个成员方法(绑定在实例上)?这意味着方法可以由多个线程在多个实例上调用,但一次只能由一个线程调用。它也可以写成同步块。

(为了说明,该方法将它的实例插入到共享缓存中。)

class DataObject {

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

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

    }
  }

}
4

3 回答 3

6

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

class DataObject {

  private static final Object cacheLock = new Object();

  public putInCache() {
    synchronized(cacheLock) {

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

    }
  }
}

请注意,对于这个特定的实现DataObject以及从它派生的所有类都将共享锁。

于 2013-02-21T13:00:12.697 回答
5

Classinstance同步是有区别的。
实例同步适用于 的每个实例Object,因此代码:

  public synchronized void putInCache() {
      // ... do some stuff
      cache.insert(this);
      // ... do some more stuff
  }

和代码

  public void putInCache() {
    synchronized(this) {
      // ... do some stuff
      cache.insert(this);
      // ... do some more stuff
    }
  }

相同之处在于它们不允许多个线程同时进入同步块;但是,这仅适用于类上的每个实例。即显示器打开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
    }
  }

它们根本不允许超过一个线程同时进入 JVM 上的同步块,即监视器在Class实例上,因此是唯一的。

您需要使用Class同步。

另一种方法是锁定资源本身,因为这是您试图阻止并发访问的内容;前提是资源不能为空并且资源的实例不会随机更改 - 如果final您可以这样做,那就更好了:

 public void putInCache() {
    synchronized(cache) {
      // ... do some stuff
      cache.insert(this);
      // ... do some more stuff
    }
  }

这使得您锁定的原因和锁定的内容非常清楚。

于 2013-02-21T13:04:33.380 回答
0

我想你正在寻找类级同步。尝试使该方法成为静态和同步的方法。例如:

public synchronized static putInCache(){
//..your code
}

这将意味着“方法可以由多个线程在多个实例上调用,但一次只能由一个线程调用。”

于 2013-02-21T13:22:29.193 回答