gpt4 book ai didi

java - 如何证明类 ListHelper 不是线程安全的

转载 作者:行者123 更新时间:2023-11-29 09:51:41 26 4
gpt4 key购买 nike

最近在看《Java Concurrency in Practice 2nd》一书,作者提到如果我们使用Collections.synchronizedList来创建一个安全的线程List,那么我们必须确保我们使用的是同一个锁,它是SynchronizedCollection中的一个对象。以下代码来自本书:

public class ListHelper <E> {
public List<E> list = Collections.synchronizedList(new ArrayList<E>());

public synchronized boolean putIfAbsent(E x) {
boolean absent = !list.contains(x);
if (absent)
list.add(x);
return absent;
}
}

在这个类中,putIfAbsent方法已经被ListHelper中的一个Object锁住了,但是list.contains并没有把这个Object当作锁,而是有两个锁,所以在多线程下是不安全的。但我的问题是如何证明它不是线程安全的。你有什么想法吗?

最佳答案

下面的代码证明你的类不是线程安全的。

它在两个不同的线程中将 100000 个数字添加到列表中:

  • t1 使用类的 putIfAbsent 方法
  • t2 使用 synchronized block 正确锁定 synchronizedList 用来控制访问的同一个“互斥”对象,即包装器列表本身.

由于这两种方法都试图添加 相同 100000 个对象,结果应该是一个包含 100000 个对象的列表,即代码应该在末尾打印 100000

有时它确实如此,当我运行它时,但大多数时候它会比那个高一点,例如100075,从而证明您的putIfAbsent 不是线程安全的。

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Test {
public static void main(String[] args) throws Exception {
ListHelper<Integer> helper = new ListHelper<>();
Thread t1 = new Thread(() -> Test.t1(helper));
Thread t2 = new Thread(() -> Test.t2(helper));
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(helper.list.size());
}
private static void t1(ListHelper<Integer> helper) {
for (int i = 0; i < 100000; i++)
helper.putIfAbsent(i);
}
private static void t2(ListHelper<Integer> helper) {
for (int i = 0; i < 100000; i++)
synchronized (helper.list) { // correct way to synchronize
if (! helper.list.contains(i))
helper.list.add(i);
}
}
}
class ListHelper <E> {
public List<E> list = Collections.synchronizedList(new ArrayList<E>());
public synchronized boolean putIfAbsent(E x) {
boolean absent = ! list.contains(x);
if (absent)
list.add(x);
return absent;
}
}

关于java - 如何证明类 ListHelper<E> 不是线程安全的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51573496/

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