gpt4 book ai didi

将对象添加到列表时的 Java 并发问题

转载 作者:行者123 更新时间:2023-11-30 06:14:34 25 4
gpt4 key购买 nike

我有一个问题看起来很奇怪,可能是因为我缺乏一些特定的知识。

我有一个简单的类 TestCon 和一个测试类 TestTest:

import java.util.*;
import java.util.concurrent.*;

public class TestCon {
private volatile static TestCon def = null;
private volatile static List<TestCon> list = Collections.synchronizedList(new ArrayList<TestCon>());

public static synchronized TestCon getInstance() {
if (def == null) {
def = new TestCon();
list.add(def);
}
return def;
}
private synchronized static TestCon addtolist(){
return new TestCon();
}
public static synchronized int getSize() {
return list.size();
}

public synchronized void destroy() {
def = null;
list.clear();
}
}


import org.testng.annotations.Test;
import org.testng.*;

public class TestTest {


@Test(threadPoolSize=50, invocationCount=15000)
public void test_getInstance() {
TestCon tst=TestCon.getInstance();
Assert.assertNotNull(tst);
Assert.assertEquals(TestCon.getSize(), 1); //line 1
tst.destroy(); //line 2
}
}

所以我的问题是为什么测试偶尔会在 //line 1 失败(列表大小为 0 但预期为 1)。如果我在测试方法中添加同步 - 一切都很好。如果我再次注释第 2 行,测试成功。

最佳答案

虽然您的 TestCon 类没有呈现明确的竞争条件,但您的测试包含一个。虽然 getInstancegetSizedestroy 方法是原子的,但这些方法的任何组合都不是。

查看您的代码:

@Test(threadPoolSize = 50, invocationCount = 15000)
public void test_getInstance() {
TestCon tst = TestCon.getInstance();
Assert.assertNotNull(tst); // (1)
Assert.assertEquals(TestCon.getSize(), 1); // (2)
tst.destroy(); // (3)
}

假设您有两个线程一起在第 (1) 行结束。然后线程 1 成功移动到第 (3) 行。这意味着,列表现在是空的。在此线程之后,线程二移动并检查 (2) 处的列表大小,发现列表为空:测试失败。

关于将对象添加到列表时的 Java 并发问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30095662/

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