简体   繁体   中英

Java achieve selective synchronization

I'm facing a problem in an application where two threads with same parameters are run, a conflict occurs. One solution was to use a synchronized block, but since the problem occurs only for threads with same params, it would be highly inefficient. One way I thought of was to use a concurrent map to store the param combination as key and an object as value, whenever a thread begins the operation it first checks if the map contains the key (param combination) and if so, it will do a wait on the object stored for that combination. The thread would at the end remove this object from the map and invoke notify on it. The problem with this approach is generating the same object for the same param combination. For ex: if thread1 inserts into map, and calls notify and removes it, thread2 may come out of wait, but other threads will never come out as the object is lost from the map.

Is there a different elegant approach to this problem?

Create a pool of parameter combinations. Every time you need to guarantee one thread is running, call Pool.acquire(params) .

Use it like this:

Wrap parameters in an object with nice hashCode and equals .

In Thread:

synchronized(pool) {
  pool.acquire(myParams);
}
// do the work
synchronized(pool) {
  pool.release(myParams);
}

Pool:

class Pool {
  Set<Params> lockedParams;

  // In Pool - note that this is synchronized!
  void acquire(Params params) {
    Params lock = lockedParams.get(params);
    if(lock != null) {
      // Locked by another thread
      lock.wait();
    }
    lockedParams.add(params);
  }

  void release(Params params) {
    Params lock = lockedParams.remove(params);
    lock.notifyAll();
  }
}

That's one idea. You need to add some error handling for real life cases ( release() in finally , in this case handle null lock in Pool.release() , etc.).

Call notifyAll instead of notify , so all waiting threads will be notified. And why do you want to remove sync object from map? Just try to acquire lock on that object, if thread succeeds, it enters critical section, otherwise it starts to wait.

You can add timeout to that wait, so if thread can't acquire lock for some period, it fails. This way your code won't go into deadlock.

如果你能代表参数(或其中的一个子集)作为一个字符串,您可以在同步interned字符串。

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