当使用任何java.util.concurrent类时,我是否仍然需要同步对实例的访问,以避免不同线程之间的可见性问题?
更详细地阐述这个问题
当使用java.util.concurrent的实例时,有没有可能某个线程修改了该实例(例如,将一个元素放入并发哈希图中),而随后的线程看不到修改?
我的问题源于这样一个事实:如果对值的访问不同步,Java内存模型允许线程缓存这些值,而不是直接从内存获取它们。
发布于 2010-10-28 14:54:03
在java.util.concurrent包Memory Consistency Properties上,您可以检查该包的Javadoc API:
java.util.concurrent及其子包中所有类的方法将这些保证扩展到更高级别的同步。特别是:
在将一个对象放入任何并发集合之前,线程中的
...在“释放”同步器方法之前执行
Lock.unlock、Semaphore.release和
CountDownLatch.countDown
发生-在成功的“获取”方法之后的操作之前,例如在另一个线程中的相同同步器对象上的Lock.lock、Semaphore.acquire、Condition.await和CountDownLatch.await。
...
因此,这个包中的类利用一组用于线程控制的类(Lock、Semaphore等)来确保并发性。这些类以编程方式处理之前发生的逻辑,即管理并发线程的先进先出堆栈,锁定和释放当前和后续线程(即使用Thread.wait()和Thread.resume()等)。
然后,(理论上)您不需要同步访问这些类的语句,因为它们以编程方式控制并发线程访问。
发布于 2010-10-28 15:39:37
因为ConcurrentHashMap (例如)被设计为在并发上下文中使用,所以您不需要进一步同步它。事实上,这样做可能会破坏它带来的优化。
例如,Collections.synchronizedMap(...)表示一种使map线程安全的方法,据我所知,它的工作原理是将所有调用包装在synchronized关键字中。另一方面,像ConcurrentHashMap这样的东西会在集合中的元素之间创建同步的“桶”,从而导致更细粒度的并发控制,从而在大量使用的情况下减少锁争用。例如,它也可能不锁定读取。如果你再次使用一些同步访问来包装它,你可能会破坏它。显然,您必须注意所有对集合的访问都是同步的,等等,这是较新的库的另一个优势;您不必担心(就像这样!)
java.lang.concurrent集合可以通过同步来实现它们的线程安全。在这种情况下,语言规范保证了可见性。他们可以在不使用锁的情况下实现一些东西。我不太清楚这一点,但我假设这里也有同样的可见性。
如果你在你的代码中看到了看起来丢失的更新,这可能只是一个竞争条件。像ConcurrentHashpMap这样的东西将为您提供读操作的最新值,而写操作可能尚未写入。这通常是准确性和性能之间的权衡。
重点是;java.util.concurrent stuff就是用来做这些事情的,所以我相信它可以确保可见性,并且不需要使用易失性和/或附加同步。
https://stackoverflow.com/questions/4040477
复制相似问题