繁体   English   中英

在使用java.util.concurrent类时,我应该同步以避免可见性问题吗?

[英]Should I synchronize to avoid visiblity issues when using java.util.concurrent classes?

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

详细阐述这个问题

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

我的问题源于这样一个事实:如果对值的访问不同步,Java内存模型允许线程缓存值而不是直接从内存中获取值。

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

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

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

因此,这个包中的类确保了并发性,利用一组类进行线程控制( LockSemaphore等)。 这个类以编程方式处理事先发生的逻辑,即管理并发线程的FIFO堆栈,锁定和释放当前和后续线程(即使用Thread.wait()Thread.resume()等。

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

因为ConcurrentHashMap(例如)旨在从并发上下文中使用,所以您不需要进一步同步它。 事实上,这样做可能会破坏它引入的优化。

例如,Collections.synchronizedMap(...)表示一种使映射线程安全的方法,据我所知,它主要通过包装synchronized关键字中的所有调用来工作。 另一方面,像ConcurrentHashMap这样的东西会在集合中的元素之间创建同步的“桶”,从而实现更细粒度的并发控制,从而在大量使用时提供更少的锁争用。 例如,它也可能无法锁定读取。 如果你再次使用一些同步访问来包装它,你可能会破坏它。 显然,你必须要小心所有对集合的访问都是syncrhronised等,这是新库的另一个优点; 你不必担心(尽可能多!)。

java.lang.concurrent集合可以通过syncrhonised实现其线程安全性。 在这种情况下,语言规范保证可见性。 他们可以在不使用锁的情况下实现。 我对此并不是很清楚,但我认为这里的可见性相同。

如果您在代码中看到丢失更新的内容,可能只是竞争条件。 像ConcurrentHashpMap这样的东西会给你一个读取的最新值,而写入可能还没有被写入。 这通常是在准确性和性能之间进行权衡。

重点是; java.util.concurrent东西是为了做这些事情,所以我相信它确保可见性和挥发性和/或加法同步化的使用不应该被要求。

暂无
暂无

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

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