简体   繁体   English

Java-同步对象/块

[英]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. A是单身人士。 getValue is heavily accessed throughout the app by multiple threads. 通过多个线程在整个应用程序中大量访问getValue。 I am adding a new method, remove, that removes a key from the map. 我正在添加一个新方法remove,它从地图上删除了一个键。 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. 当线程处于remove方法的同步块中时,我假设它将获得对map对象的锁定。 Does that mean other threads trying to access the map via the getValue method will be blocked? 这是否意味着其他试图通过getValue方法访问地图的线程将被阻止? (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? 如果在remove方法的同步块中没有线程,则访问getValue方法的线程是否会照常运行,即不会互相阻塞? (I'd like that too). (我也想要)。

I want the getValue threads to block only if there is a thread performing the remove operation. 我希望getValue线程仅在有线程执行删除操作时才阻塞。

When a thread is in the synchronized block of the remove method, I assume it will acquire a lock on the map object. 当线程处于remove方法的同步块中时,我假设它将获得对map对象的锁定。 Does that mean other threads trying to access the map via the getValue method will be blocked? 这是否意味着其他试图通过getValue方法访问地图的线程将被阻止?

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? 如果在remove方法的同步块中没有线程,则访问getValue方法的线程是否会照常运行,即不会互相阻塞? (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. 同样,您需要确保使用的任何Map实现都可以,尽管比同时编写要阅读的可能性更大。

You should consider using a ConcurrentMap implementation (eg ConcurrentHashMap ), at which point you don't need any synchronization at all. 您应该考虑使用ConcurrentMap实现(例如ConcurrentHashMap ),此时您根本不需要任何同步。

If you can't use that, I'd recommend synchronizing in both getValue and remove - and measuring the performance. 如果你不能使用,我建议在这两个同步getValueremove -以及测量性能。 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.) (当然,使用ConcurrentHashMap是避免问题的一种相当简单的方法,但是在开始进行微优化之前,您应该始终考虑是否需要额外的复杂性来实现所需的性能。)

如果我正确理解了您的需求,则可以看看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 1. getValue()不同步,当线程获取对象的锁时,它可以控制所有同步块...而不是非同步块。因此, 其他线程可以访问getValue()线程处于同步(map)块中

2. Use HashTable, which is a sychronized MAP 2.使用HashTable,这是一个同步的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. 我希望getValue线程仅在有线程执行删除操作时才阻塞。

Without some sort of inter-thread interaction, you cannot figure out whether there is some other thread performing a remove . 没有某种类型的线程间交互,您将无法确定是否有其他线程执行remove

The correct way to implement getValue(...) is to synchronize on the map. 实现getValue(...)的正确方法是在地图上进行同步。

I recommend dropping your own locking, and using a ConcurrentHashMap and utilizing a lot of work into concurrent performance. 我建议删除您自己的锁定,并使用ConcurrentHashMap并将大量工作用于并发性能。

The one rule of synchronized is that only one thread can be in a synchronized(foo) block at a time, for the same foo. 同步的一个规则是,对于同一个foo,一次只能有一个线程处于synchronized(foo)块中。 That's the only rule of synchronized . 这是唯一的规则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: 嗯,有关于记忆障碍等的一些复杂的东西,和一个单独的线程可以在几个嵌套synchronized(foo)为同一区块foo在同一时间:

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 . ...但是上述规则基本上是理解synchronized的关键。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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