我编写了一个多线程和同步递增函数,但它没有显示一致的输出: -
$ java Main
count: 999883
$ java Main
count: 1000000
$ java Main
count: 999826
$ java Main
count: 1000000
$ java Main
count: 1000000
我有一个同步计数器: -
public class Counter {
public int count;
synchronized void inc() {
count = count+1;
}
int getCount() {
return count;
}
}
使用计数器对象初始化的线程类,并将其递增1000次: -
public class CountPrimesRunnable implements Runnable {
private Counter c;
public CountPrimesRunnable(Counter c) {
this.c = c;
}
public void run() {
for (int i = 0; i < 1000; i++)
c.inc();
}
}
一次创建1000个线程的Main类: -
public class Main {
public static void main(String[] args) {
int numberOfThreads = 1000;
Thread[] worker = new Thread[numberOfThreads];
Counter c = new Counter();
for (int i = 0; i < numberOfThreads; i++)
worker[i] = new Thread(new CountPrimesRunnable(c));
for (int i = 0; i < numberOfThreads; i++)
worker[i].start();
System.out.println("count: " + c.count);
}
}
我错过了什么?
答案 0 :(得分:4)
但它没有显示一致的输出: -
那是因为,从代码中可以确定main
线程在所有其他线程完成其工作后总是会完成。在某些情况下,如果得到的结果小于1000000
,则在主线程完成后某些线程仍然执行的情况下。
您可以在每个新创建的线程上调用Thread#join()
方法,以确保main
方法等待所有这些线程死亡,然后在for循环后继续执行。
因此,您必须添加另一个for循环以在每个启动的线程上调用join
,并且您还可以避免使用第二个for循环,将其与第一个循环合并:
for (int i = 0; i < numberOfThreads; i++) {
worker[i] = new Thread(new CountPrimesRunnable(c));
worker[i].start();
}
for (int i = 0; i < numberOfThreads; i++) {
worker[i].join();
}
当您从join
内部Thread A
调用Thread B
时,Thread B
将仅在Thread A
死亡后继续执行。
答案 1 :(得分:1)
public class Counter {
public int count;
synchronized void inc() {
count = count+1;
}
//this method must also be synchronized for establishing the happens-before relationship
synchronized int getCount() {
return count;
}
}
只有当get和set在同一个锁上同步时,才能保证您会看到最新的值。
此外,您需要调用join并等待所有线程完成执行。