public class Worker {
private int count = 0; //shared resource
public static void main(String[] args) {
Worker w = new Worker();
w.doWork();
}
public void doWork() {
Thread thread1 = new Thread(new Runnable() { //Thread incrementing count 10000 times
public void run() {
for (int i = 0; i < 10000; i++) {
count++; //Not Atomic operation
}
}
});
Thread thread2 = new Thread(new Runnable() { //Thread incrementing count 10000 times
public void run() {
for (int i = 0; i < 10000; i++) {
count++; //Not Atomic operation
}
}
});
thread1.start();
thread2.start();
try {//halts main thread so that both thread race to increment count
thread1.join();
thread2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Count is: " + count);
}
}
我从Cave Of Programming复制了这段代码。 每次运行此代码时,我都会将结果显示为20000而不使用synchronized关键字,这是意外的。 代码是否正确? 我的操作系统正确安排了两个线程? (我知道这很奇怪问题)
每次运行代码时,我都期待不必要的结果。
答案 0 :(得分:1)
首先,count ++不是原子的。 其次,虽然你的答案是正确的2000,但我们不能保证它总是正确的。
原因如下。操作计数++被视为一个3步骤过程
1. Fetch the count value
2. Increment the count value
3. assign the incremented value back to count variable
因此,当thread1正在读取时,线程2可能会增加该值。仍然线程1具有ole值,并且覆盖了thread2
所包含的值如果你使count ++原子,我肯定是正确的。为此,您可以使用如下
AtomicInteger count = new AtomicInteger();
你可以使用
增加它 count.incrementAndGet();
答案 1 :(得分:1)
根据操作系统和系统负载,它的行为会有所不同。
我执行了相同的代码3次,每次都得到不同的结果
$ java工作人员 数量是:10437
$ java工作人员 数量是:10395
$ java工作人员 数量是:10684
我使用Ubuntu 14(x64)和OpenJDK-7
答案 2 :(得分:0)
预期输出是两个线程都将count变量从0递增10000,因此预期输出确实为0 + 10000 + 10000 = 20000。
但是,由于count ++不是原子操作,因此这不是确定性的。再运行一次,你可能得到不同的结果。
答案 3 :(得分:0)
代码不正确。正确的结果是巧合。
首先计算++不是原子的。
其次,任务可能会一直运行直到结束,另一个任务可以在之后运行 - 这里没有限制。时间表可以决定给予一个任务实际完成的时间,而不是切换,或者它只是提供足够的时间来计算++实际上表现得像原子(仅仅因为交换机之间的时间)。但是可能会提供不同的结果。最终,2000年只是一个幸福的巧合。
尝试增加循环大小,以便查看不同的结果。 总之,代码是正确的,以提供不正确的结果,如您所料,只需扩展实验。
答案 4 :(得分:0)
根据你的代码,你的for循环将在两个套装中执行10000次,所以很明显它会给你20000个结果。
建议:尝试打印 window.oncontextmenu = function (event) {
event.preventDefault();
event.stopPropagation();
return false;
};
count
然后,您将意识到与Thread thread1 = new Thread(new Runnable() { //Thread incrementing count 10000 times
public void run() {
for (int i = 0; i < 10000; i++) {
count++; //Not Atomic operation
System.out.println(count);
}
}
});
和synchronized
的区别。
答案 5 :(得分:0)
@Javed ..我希望你已经看到了线程中的连接基础.. 看起来Join正在为你和我工作...... 我已经运行了你的程序10次,总是有20000。 我之前尝试过一个SOP,比如Thread.currentThread()。getName() 两个线程中的count ++然后运行程序。 我发现thread1之间没有交错 和thread2 ...然后显示Thread1的所有SOP 显示Thread2的SOP,因此没有比赛.. Thread1完成它的工作,然后Thread2完成它的工作 因此20000将永远是结果。