简体   繁体   中英

Member method synchronized on whole class

After some quick searching, I was not able to find a clear answer.

Is there some more elegant way to synchronize a whole member method (bound on instance) on whole class? This means method can be called on multiple instances by multiple threads, but only by one thread at the time. It can be written also as a synchronized block.

(For illustration, the method inserts it's instance into shared cache.)

class DataObject {

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

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

    }
  }

}

It's a good idea to avoid synchronizing on publicly accessible object. You can use a shared monitor object, however:

class DataObject {

  private static final Object cacheLock = new Object();

  public putInCache() {
    synchronized(cacheLock) {

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

    }
  }
}

Note that with this particular implementation DataObject and all classes derived from it will share the lock.

There is a difference between Class and instance synchronization.
Instance synchronization works on each instance of the Object , so the code:

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

And the code

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

Are equivalent in that they do not allow more than one thread to enter the synchronized block simultaneously; however this is only for each instance on the class. ie the monitor is on this

Class synchronization works on the Class itself, the following two blocks are also equivalent:

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

They do not allow more than one thread to enter the synchronized block simultaneously at all across the JVM, ie the monitor is on the Class instance and so unique.

You need to use Class synchronization.

An alternative is to lock the resource itself as that is what you are trying to prevent concurrent access to; provided the resource cannot be null and the instance of the resource does not randomly change - even better if it's final you can do this:

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

This makes it very clear why you are locking and what you are locking.

i guess u are looking for class level synchronization. try to make the method a static and synchronized one. eg:

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

this will mean "method can be called on multiple instances by multiple threads, but only by one thread at the time."

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM