首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将对象添加到列表时出现Java并发问题

将对象添加到列表时出现Java并发问题
EN

Stack Overflow用户
提问于 2015-05-07 16:26:26
回答 2查看 61关注 0票数 2

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

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

代码语言:javascript
运行
复制
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行,则测试成功。

EN

Stack Overflow用户

发布于 2015-05-07 17:05:12

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

看看你的代码:

代码语言:javascript
运行
复制
@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移动并检查(2)处的列表大小,发现列表为空:测试失败。

票数 3
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30095662

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档