简体   繁体   中英

Java - Synchronized Object/Block

I am looking for clarification about synchronized blocks. Consider this class -

public class A{
Map map;

 public getValue(String key){
  return map.get(key);
 }

 public remove(String key){
  synchronized(map){
   map.remove(key);
  }
 }
}

A is a singleton. getValue is heavily accessed throughout the app by multiple threads. I am adding a new method, remove, that removes a key from the map. If remove is implemented as above,

  1. When a thread is in the synchronized block of the remove method, I assume it will acquire a lock on the map object. Does that mean other threads trying to access the map via the getValue method will be blocked? (I'd like them to.)
  2. When no thread is in the synchronized block of remove method, will threads accessing the getValue method function as usual ie not block each other? (I'd like that too).

I want the getValue threads to block only if there is a thread performing the remove operation.

When a thread is in the synchronized block of the remove method, I assume it will acquire a lock on the map object. Does that mean other threads trying to access the map via the getValue method will be blocked?

No. Which means you've got a problem, unless you happen to be using a thread-safe map implementation.

When no thread is in the synchronized block of remove method, will threads accessing the getValue method function as usual ie not block each other? (I'd like that too).

They won't block each other, no. Again, you'll need to make sure that's okay with whichever Map implementation you're using, although it's much more likely to be okay than reading at the same time as writing.

You should consider using a ConcurrentMap implementation (eg ConcurrentHashMap ), at which point you don't need any synchronization at all.

If you can't use that, I'd recommend synchronizing in both getValue and remove - and measuring the performance. Acquiring an uncontended lock is reasonably cheap - do you really need to go lock-free? (Using ConcurrentHashMap is a fairly simple way of avoiding the issue, of course, but you should always consider whether extra complexity is needed to achieve the performance you require before you start micro-optimizing.)

如果我正确理解了您的需求,则可以看看ConcurrentMap ,当然还有ConcurrentHashMap ,我相信它是Java 5.0引入的,并支持一定程度的并发性。

您没有显示如何实例化Map实例,但是假设它不是线程安全的集合实例,则此代码不是线程安全的。

1. getValue() is not synchronized, when a thread acquires the lock of an object, it has the control over all the synchronized blocks... not the Non-synchronized one.. So other threads can access the getValue() when as thread is in sychronized(map) block

2. Use HashTable, which is a sychronized MAP

You have a chicken and egg problem with

I want the getValue threads to block only if there is a thread performing the remove operation.

Without some sort of inter-thread interaction, you cannot figure out whether there is some other thread performing a remove .

The correct way to implement getValue(...) is to synchronize on the map.

I recommend dropping your own locking, and using a ConcurrentHashMap and utilizing a lot of work into concurrent performance.

The one rule of synchronized is that only one thread can be in a synchronized(foo) block at a time, for the same foo. That's the only rule of synchronized .

Well, there's some complicated stuff about memory barriers and the like, and a single thread can be in several nested synchronized(foo) blocks for the same foo at the same time:

void thing() {
  synchronized(foo) {
    stuff(); // this works fine!
  }
}
void stuff() {
  synchronized(foo) {
    doMoreStuff();
  }
}

... but the rule stated above is basically the key to understanding synchronized .

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