当使用任何Java.util.concrurent类时,我是否仍然需要同步该实例上的访问以避免差异线程之间的可见性问题?

详细说明问题

当使用Java.util.concurrent的实例时,一个线程是否可能修改实例(即,将元素放入并发hashmap中),并且随后的线程不会看到修改?

我的问题源于以下事实:Java内存模型允许线程缓存值,而不是如果未同步该值的访问,而不是直接从内存中获取它们。

有帮助吗?

解决方案

在java.util.concurrent软件包上 内存一致性属性, ,您可以检查Javadoc API中的包装:

Java.util.concurrent及其子包的所有类的方法将这些保证扩展到更高级别的同步。尤其是:

  • 在将对象放入任何并发集合中之前,在线程中的操作 发生在之前 在另一线程中从集合中访问或删除该元素之后的操作。
    [...]
  • 在“释放”同步方法之前的操作,例如
    lock.unlock,Semaphore.Release和
    CountDownLatch.Countdown
    发生在之前 成功的“获取”方法之后的操作,例如lock.lock.lock,Smahaphore.Acquire,condition.await和Countdownlatch.await在另一个线程中的同一同步对象上。
    [...]

因此,此软件包中的类确保并发,使用一组用于线程控制的类(Lock, Semaphore, , ETC。)。该课程处理 发生在之前 从逻辑上讲,IE管理同一线程的FIFO堆栈,锁定和释放电流和后续线程(即使用 Thread.wait()Thread.resume(), , ETC。

然后,(理论上)您不需要同步您的语句访问此类,因为它们正在以编程方式控制并发线程访问。

其他提示

由于contrenthashmap(例如)被设计为从并发上下文中使用,因此您无需进一步同步。实际上,这样做可能会破坏其引入的优化。

例如,collections.synchronizedmap(...)代表了一种使映射线程安全的方法,据我了解,它基本上可以通过将所有调用包装在同步关键字中。另一方面,诸如ConturrentHashMap之类的东西会在集合中的元素上产生同步的“存储桶”,从而导致较细的并发控制,因此在大量使用情况下会减少锁定的争论。例如,它也可能不会锁定读取。如果您再次使用一些同步访问包装,则可能会破坏这一点。显然,您必须小心,所有对该藏品的访问均已同步等等,这是较新库的另一个优点。您不必担心(太多!)。

Java.lang.concrurnent收集可以通过Syncrhonised实施其线程安全性。在这种情况下,语言规范可以保证可见性。他们可能无需使用锁即可实施事物。我对此并不清楚,但我认为这里的可见性也是如此。

如果您看到代码中看起来像丢失的更新,那可能只是比赛条件。诸如confurrenthashpmap之类的东西将为您带来读取的最新价值,并且可能还没有编写文字。这通常是准确性和性能之间的权衡。

重点是; java.util.concurrent的内容旨在做这些事情,因此我相信它可以确保不需要挥发性和/或添加的同步化。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top