Java多线程竞争条件场景
我正在经历多线程中的竞争条件,并且想到创建导致竞争条件的情况,我为此写了一个简单的程序,但每次都得到正确的结果。需要知道这是否是比赛状况的正确情况。如下Java多线程竞争条件场景
代码:
package com.threads;
/**
* demonstrate race conditions
*/
public class Step4 {
public int getA() {
return a;
}
public void addToA(int number) {
for(int i=0;i<number;i++)
this.a = this.a + 1;
}
int a = 2;
static Step4 s4 = new Step4();
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
s4.addToA(5);
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
s4.addToA(3);
}
});
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
s4.addToA(6);
}
});
Thread thread4 = new Thread(new Runnable() {
@Override
public void run() {
s4.addToA(4);
}
});
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread1.join();
thread2.join();
thread3.join();
thread4.join();
System.out.println(s4.getA());
}
}
//输出20总是在我的机器中,Win7 32位。
由于所有线程都添加到字段a,所以该命令确实会影响最终结果,因此您的程序由于竞争状态而遭受的可能性非常低。 只有当两个线程读取相同的值a,然后第一个分配一个新的值,然后第二个分配一个新的值,你可以“失去”一个增量。
下面是修改后的版本更频繁地从竞争条件患有:
public class Step4 {
public int getA() {
return a;
}
public void addToA(int number) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i=0;i<number;i++)
this.a = this.a + 1;
}
public void multiplyA(int number) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.a = this.a * number;
}
int a = 2;
static Step4 s4;
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
s4 = new Step4();
doRun();
System.out.println("*******");
}
}
private static void doRun() throws InterruptedException {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
s4.addToA(5);
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
s4.multiplyA(3);
}
});
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
s4.addToA(6);
}
});
Thread thread4 = new Thread(new Runnable() {
@Override
public void run() {
s4.addToA(4);
}
});
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread1.join();
thread2.join();
thread3.join();
thread4.join();
System.out.println(s4.getA());
}
}
我添加了一个100毫秒的睡眠这两个动作,以增加获得不同的结果的机会。 大部分时间结果将是31,但在其他时间可能是17,21或51。
它确实遭受竞争状态的影响。两个线程可以并行读取a的当前值,然后增加它,这样就会失去一个增量。 –
@JBNizet,是的,这是真的。我编辑了答案。 –
您的代码确实模拟竞态条件,因为添加涉及读取和写入。但是为了在这里真实地展示竞争性,你需要一些非常不幸的调度,因为所有的线程都是加法。您可能想要尝试在不同的机器上运行此操作,或者让一些线程执行其他操作,例如devision或subtraction。
另一种方法是通过在addTo()
中添加来确保竞争条件。
很可能每个线程在这里做的工作很少,以至于它们根本不重叠。 –
您正在等待所有4个线程来完成(join()方法),所以当然,一旦** println **被调用,内容始终为20.所以不,它不会模拟竞态条件。 –
使涉及的数字更大。竞争条件是不可预测的,因此每个线程花费更多时间会增加发生的可能性。 – Kiskae