我不明白为什么计数器的输出每次都是一个不同的随机数。当我在run()方法中打印出计数器时,它每次都是100000,但是当我对该语句进行注释时,它会给出一个随机数。
public class Answer extends Thread {
private static int counter = 0;
private static final int THREADS = 4;
public static final int COUNT = 100000;
public static void main(String[] args) {
Answer[] threads = new Answer[THREADS];
for (int i = 0; i < THREADS; i++) {
threads[i] = new Answer();
threads[i].start();
}
try {
for (int i = 0; i < THREADS; i++) {
threads[i].join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Counter: " + counter);
}
public void run() {
for (int i = 0; i < COUNT/THREADS; i++) {
counter++;
//System.out.println(counter);
}
} }
答案 0 :(得分:1)
操作
counter++
你的线程代码中的不是线程安全的。你的主题正在踩着彼此的行动。
幸运的是,println的线程安全部分正在充分同步线程的操作,以防止静态变量的不利交互。当您注释掉println调用时,您将丢失该幸运同步。
如果您需要使用这样的东西进行制作,可以使用同步变量。
答案 1 :(得分:1)
以下两个原因。
<强>计数器++ 强>
这不是线程安全的。
实施例。
计数器= 0。
线程1&amp;线程2尝试同时增加该值。两者都将从主存中获取值。线程内存增加。所以现在计数器是1.主内存更新为1而不是2。
您可以使用volatile
或AtomicInteger
来解决此问题。
主题安排:
线程调度由OS完成。订单无法保证。即使您以相同的顺序提交thread1&amp; thread2&amp; thread3。它可能以不同的顺序运行。
答案 2 :(得分:0)
您的计数器变量是静态的,并且在您创建的所有线程之间共享,并且每个线程都在自行更改计数器。尝试删除&#39;静态&#39;来自计数器变量。
此:
private static int counter = 0;
对此:
private int counter = 0;
答案 3 :(得分:0)
counter
是未受任何锁定或同步保护的线程之间的共享变量,因此各种线程上的counter++
语句将以不可预测的方式“相互踩踏”。据推测,println
引入了足够的延迟来抵消这种情况,尽管这不能保证100%。你有什么尝试来完成......?!