Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么java并发集合真的是线程安全的_Java_Multithreading_Collections_Concurrency_Thread Safety - Fatal编程技术网

为什么java并发集合真的是线程安全的

为什么java并发集合真的是线程安全的,java,multithreading,collections,concurrency,thread-safety,Java,Multithreading,Collections,Concurrency,Thread Safety,我在看java并发集合的代码,我看到它们只是包装简单集合,在操作开始时锁定一些锁,最后解锁它 那volatile呢?如果后端集合不是易失性的,那么其他线程可能会错过这些更改,因此线程保存有些中断。我知道synchronized可以解决这个问题,但它们只使用锁,不需要进一步同步 这是个问题,还是我遗漏了什么 更新: 经过一番小小的讨论,我想把这个问题重新措辞一下 我想在多线程环境中使用java集合。(例如,目前我谈论的是PriorityBlockingQueue) 我希望确保一个线程对集合(pu

我在看java并发集合的代码,我看到它们只是包装简单集合,在操作开始时锁定一些锁,最后解锁它

那volatile呢?如果后端集合不是易失性的,那么其他线程可能会错过这些更改,因此线程保存有些中断。我知道
synchronized
可以解决这个问题,但它们只使用锁,不需要进一步同步

这是个问题,还是我遗漏了什么


更新:

经过一番小小的讨论,我想把这个问题重新措辞一下

我想在多线程环境中使用java集合。(例如,目前我谈论的是
PriorityBlockingQueue

我希望确保一个线程对集合(push/pop)所做的更改对其他线程立即可见

java并发集合可以防止我陷入麻烦,从而在线程数更新集合时保持集合的内部状态稳定,这是很好的,但是 我想确保数据本身对所有线程都是可见的

问题是:java并发集合没有提供这种现成的特性,我说的对吗?如果我这样做了,我应该使用什么额外的(最低成本)技术来提供所需的可见性


谢谢。

编辑:由于原始问题已澄清,此答案不再相关。下面的答案与使用方法使非线程安全集合线程安全的情况相关


如果同步的代码块也会导致不同线程同步(可能已更改)状态

[……] 任何一种解决方案都需要将
clkID
变量与主内存协调。从synchronized方法或块访问
clkID
变量不允许该代码同时执行,但它确实保证主内存中的
clkID
变量得到适当更新。当在受保护代码执行之前获得对象锁,然后在受保护代码执行之后释放锁时,主存将更新。 [……]

来源

我在看java的代码 并发集合,我看到了 它们只是将简单的集合用 在开始时锁定一些锁 操作并在中将其解锁 结束

你在读什么资料

这是一种过度概括。这完全取决于你在看哪个系列。例如,
CopyOnWriteArrayList
不进行任何排序,但每次添加或删除元素时都会创建一个全新的数组,这意味着任何打开的
迭代器或
列表迭代器将继续使用旧数据运行;这种效果是有意的

挥发性的呢?如果后端 集合不随更改而变化 可能会被其他线程错过,以及 因此,节省线程有点困难 破碎的我知道你可以 解决这个问题,但他们只使用 没有任何进一步的限制 同步


大多数并发集合的存在是为了确保迭代器继续在旧版本上运行,而不是在更新了数据的新版本上运行;不稳定的东西不能保证。此行为还意味着迭代器不会处于不一致的状态,从而防止抛出
ConcurrentModificationException

是的,您缺少了一些内容。ReentrantLock类提供与synchronized相同的保证。而且,ReentrantLock和synchronized都提供了与volatile相同的内存保证

来自的Javadoc:

内存一致性影响:与其他并发集合一样,在将对象放入
阻塞队列
之前,线程中的操作发生在另一个线程中从
阻塞队列
访问或移除该元素之后的操作之前

PriorityBlockingQueue
通过
ReentrantLock
提供此行为,它(是的一个实现):

…提供与内置监视器锁相同的内存同步语义,如


以下是对您的问题的要点式回答。 1.并发包中的所有Java集合数据结构都不会包装相应的非线程安全集合数据结构。 2.有一些方法可以在不使用锁或同步的情况下实现线程安全。编写无锁数据结构更复杂,通常您应该避免进行一般开发。但是,如果有可用的锁,则应该使用它们,而不是数据结构的相应锁版本。 3.无锁数据结构不使用锁,仍然提供所有的安全性和活性属性。
4.示例API是ConcurrentSkipListMap,它是无锁并发概率映射(可能是Java中最复杂的实现)

我理解这一点,但并发集合的目的不是为了避免任何其他显式同步吗?如果我错了,请纠正我。我不确定我是否理解你的问题。“任何其他显式同步”是什么意思?synchronized collection wrapper的作用是同步对其他非线程安全集合的访问。正如Bemrose所提到的,如果您明确说明您正在查看的类源,这将非常有用。@Neeme Praks如果您在包装原始集合后保留它,然后通过这种方式访问它,您已经绕过了包装器添加的“显式同步”。锁是“建议性”的,因为各方必须同意使用同一个监视器(或根本不锁定)。我指的是
同步的
块。所以每次我访问线程时-