gpt4 book ai didi

java - 同步和并发集合如何是线程安全的,但它们的内容不是

转载 作者:行者123 更新时间:2023-12-03 11:18:54 24 4
gpt4 key购买 nike

从这里 source可以阅读:

It's worth mentioning that synchronized and concurrent collectionsonly make the collection itself thread-safe and not the contents.


我想如果 Collection是线程安全的,那么它的内容将隐式是线程安全的。
我的意思是如果两个线程不能访问我的 Collection对象然后是我的对象 Collection持有的对象将隐式变为线程安全的。
我错过了这一点,有人可以用一个例子来解释我吗?

最佳答案

tl;博士
存储在线程安全集合中的对象可以泄漏到外部并以非线程安全的方式使用。
详细解答:

I thought if Collection is thread-safe then its content willimplicitly be thread-safe, I mean if two threads cannot access myCollection object then the object which my Collection object isholding will implicitly become thread-safe.

I know sure I missing the point, could someone please explain me withan example.


考虑以下使用两个线程添加到同一 的代码。非线程安全列表 来自 0 to 10 的元素.最后,主线程对该列表的所有元素求和。最终结果应该与 0 + 0 + 1 + 1 + ... 9 + 9 = 90. 相同然而,如果你多次执行代码,你会得到不同的值,有时甚至是下面的 NPE :
Exception in thread "main" java.lang.NullPointerException
at java.base/java.util.stream.ReduceOps$1ReducingSink.accept(ReduceOps.java:80)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:553)
at Z.CollectionThreadSafe.main(CollectionThreadSafe.java:26)
所有这些都是方法调用期间竞争条件的结果 add .
private static void addToList(List<Integer> list) {
for (int i = 0; i < 10; i++)
list.add(i);
}

public static void main(String[] arg) throws InterruptedException {
final int TOTAL_THREADS = 2;
List<Integer> list = new ArrayList<>();
ExecutorService pool = Executors.newFixedThreadPool(TOTAL_THREADS);
for (int i = 0; i < TOTAL_THREADS; i++) {
pool.submit(() -> addToList(list));
}
pool.shutdown();
pool.awaitTermination(10, TimeUnit.SECONDS);
System.out.println(list.stream().reduce(0, Integer::sum));
}
让我们使用线程安全 List 修复竞争条件调用 Collections.synchronizedList .因此,让我们将之前的代码修改为:
List<Integer> list = Collections.synchronizedList(new ArrayList<>());
您可以根据需要多次运行它;最终结果总是相同的,即 90 .我们已经知道了这么多。让我们展示一下:

It's worth mentioning that synchronized and concurrent collectionsonly make the collection itself thread-safe and not the contents.


您只需要修改之前的代码:
List<Integer> list = Collections.synchronizedList(new ArrayList<>());
到:
final List<List<Integer>> LIST_THREAD_SAFE = Collections.synchronizedList(new ArrayList<>());
LIST_THREAD_SAFE.add(new ArrayList<>());
List<Integer> list = LIST_THREAD_SAFE.get(0);
...
瞧!您的情况与我们展示的第一个示例完全相同(即竞争条件)。即使列表 LIST_THREAD_SAFE是线程安全的,它的内容不是。因此,

synchronized and concurrent collections only make the collectionitself thread-safe and not the contents.

关于java - 同步和并发集合如何是线程安全的,但它们的内容不是,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66059994/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com