我是Java的新手并且在玩线程。我编写了这个小程序来检查3个线程访问非同步方法时会发生什么:
class SharedValueHolder {
public static int globalCounter = 0;
public static void increment() {
globalCounter++;
}
}
class Incrementor implements Runnable {
public void run() {
for (int i = 0; i < 5; i++) {
//reportValue();
SharedValueHolder.increment();
}
}
private void reportValue() {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + " - " + SharedValueHolder.globalCounter);
}
}
public class ThreadTest {
public static void main(String... args) throws InterruptedException {
runTest();
}
private static void runTest() throws InterruptedException {
Thread thread1 = new Thread(new Incrementor());
Thread thread2 = new Thread(new Incrementor());
Thread thread3 = new Thread(new Incrementor());
thread1.start();
thread2.start();
thread3.start();
Thread.sleep(300);
System.out.println(SharedValueHolder.globalCounter);
}
}
令人惊讶的是,结果几乎总是15.有时我会得到14,但这非常罕见。
现在,如果我取消注释reportValue()
中对Incrementor.run
的调用,我会看到类似这样的内容:
Thread-2 - 0
Thread-1 - 0
Thread-0 - 0
Thread-0 - 3
Thread-0 - 4
Thread-0 - 5
Thread-0 - 6
Thread-1 - 2
Thread-1 - 8
Thread-1 - 9
Thread-1 - 10
Thread-2 - 1
Thread-2 - 12
Thread-2 - 13
Thread-2 - 14
这清楚地表明线程&#34;见&#34;在相同的时间相同的值,但结果仍然是正确的。有人可以向我解释这是如何运作的吗?
答案 0 :(得分:2)
并发不是一个简单的主题,其中一个棘手的原因是因为有时你可能得到一个正确的结果(并认为你的代码是好的),但这并不意味着代码是真的很对它意味着给定你运行它的环境,线程的数量......它工作得很好。但它可能会在高度并发的环境中失败。
但是,你说你看到了相同的结果几乎总是,这并不总是如此。
它也是您问题的范围,仅包含5个元素的循环。可能第二个和第三个线程甚至在第一个线程结束时都没有开始。
但很容易看出它的错误。请尝试运行此示例:
class SharedValueHolder {
public static int counter = 0;
}
class Incrementor implements Runnable {
public void run() {
for (int i = 0; i < 100000; i++) {
SharedValueHolder.counter++;
}
}
}
public class ThreadTest {
public static void main(String... args) throws InterruptedException {
Thread thread1 = new Thread(new Incrementor());
Thread thread2 = new Thread(new Incrementor());
thread1.start();
thread2.start();
Thread.sleep(2000);
System.out.println(SharedValueHolder.counter);
}
}
两个线程增加100.000,所以你最终会期望200.000。但相反,我得到了:
102472
105560
121472
139343
120953