宝哥软件园

在Java内存模型中测试并发程序代码

编辑:宝哥软件园 来源:互联网 时间:2021-09-09

让我们看看这段代码:

导入Java . util . BitSet;导入Java . util . concurrent . countdowlatch;公共类an example { public static void main(String[]args)引发异常{ BitSet bs=new BitSet();countdowlatch锁存器=新的countdowlatch(1);Thread t1=new Thread(new Runnable(){ public void run(){ try { latch . wait();thread . sleep(1000);} catch(Exception ex){ } bs . set(1);} });Thread T2=new Thread(new Runnable(){ public void run(){ try { latch . wait();thread . sleep(1000);} catch(例外e){ } bs . set(2);} });t1 . start();T2 . start();latch .倒计时();t1 . join();T2 . join();//此处关键部分: system . out . println(bs . get(1));system . out . println(bs . get(2));}}问题来了。这段代码的输出结果是什么?它能输出什么结果,上面的程序即使在崩溃的JVM上也能打印出什么结果?

让我们看看这个程序是做什么的:

初始化BitSet对象的两个线程并行运行,并将第一位和第二位的字段值分别设置为true。我们试图让这两个线程同时运行。读取BitSet对象的值,然后输出结果。接下来,我们需要构建一些测试用例来检查这些行为。显然,其中一个只能运行示例,然后观察结果并回答上述问题。然而,回答第二个关于允许输出结果的问题需要一些技巧。

熟能生巧

幸运的是,我们可以使用工具。JCStress是解决这类问题的测试工具。

我们可以用JCStress可以识别的形式轻松地编写测试用例。事实上,它已经在许多可能的情况下为我们准备了接口。我们需要一个例子。在本例中,两个线程同时执行,执行结果表示为两个布尔值。

我们使用actor 2 _ arbiter1 _ testBitSet,boolean result2接口,它将为我们的两个线程提供一些方法块和一个转换方法,这个转换方法将表示BitSet状态的结果转换成一对布尔值。我们需要找到一个Java 8 JVM来运行它,但是现在这已经不是问题了。

请看下面的实现。是不是特别简洁?

public class AnExampleTest实现Actor2 _ Arbiter1 _ TestBitSet,booleanrefult 2 { @ Override public void actor 1(BitSet s,booleanrefult 2 r){ s . set(1);} @ Override public void actor 2(BitSet s,booleanresult 2 r){ s . set(2);} @ Override public void arbitter 1(BitSet s,booleanresult 2 r){ r . R1=s . get(1);r . R2=s . get(2);} @ Override public BitSet newState(){ return new BitSet();} @重写公共BooleanResult2 newResult() {返回新的booleanresult 2();}}现在,在运行这个测试时,控件将尝试各种技巧来获取驱动这些动作的因素的所有可能组合,并行或不并行,有无负载检测,并在一行中做多次,因此所有可能的结果都将被记录下来。

当你想知道你的并行代码是如何工作的,这比你自己想办法弄清楚所有的细节要好。

此外,为了利用JCStress约束带来的综合便利,我们需要向它提供可能结果的解释。为此,我们需要使用一个简单的XML文件,如下所示。

测试名称=' org。打开JDK。jcstress。测试。定制。' anexampletest '投稿人:Shelajev/投稿人说明测试BitSet在没有同步的情况下是否工作正常描述大小写匹配[真,真]/匹配预期可接受/预期描述完整查看所有更新/描述/案例案例匹配[真,假]/匹配预期兴趣/预期描述T2覆盖一种网络的名称(传输率可达1.54mbps)结果/描述/案例案例匹配[假,真]/匹配预期兴趣/预期描述T1覆盖T2结果。/描述/案例不匹配预期禁止/预期描述所有其他案例都是意外的。/描述/不匹配/测试现在,我们已经准备好让这头野兽开始咆哮了。通过使用下面的命令行运行测试。

Java-XX :解锁诊断VM options-XX : WhiteBoxAPI-XX :-限制满足-jar测试-自定义/目标/jcstress。jar-t=' .*一个完整的测试而我们所得到的结果是一份优雅的报告。

2015710111243724.png  (955280)

现在很清楚的是,我们不仅可以得到预期的结果,即两个线程都已经设置了它们的位,也遇到了一个竞争条件,一个线程将覆盖另一个线程的结果。

即使你看到发生了这种事情,也一定要有"山人自有妙计"的淡定心态,不是吗?

顺便说一下,如果你在思考如何修改这个代码,答案是仔细阅读Javadoc中的BitSet类,并意识到那并非是线程安全的,需要外部同步。这可以很容易地通过增加同步块相关设定值来实现。

同步(bs){ bs。集合(1);}

更多资讯
游戏推荐
更多+