public class ThreadsDemo {
public static int n = 0;
private static final int NTHREADS = 300;
public static void main(String[] argv) throws InterruptedException {
final CountDownLatch cdl = new CountDownLatch(NTHREADS);
for (int i = 0; i < NTHREADS; i++) {
new Thread(new Runnable() {
public void run() {
// try {
// Thread.sleep(10);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
n += 1;
cdl.countDown();
}
}).start();
}
cdl.await();
System.out.println("fxxk, n is: " + n);
}
}
为什么输出是&#34; n是:300&#34;? n未明确同步。如果我取消注释&#34; Thread.sleep&#34;,则输出为&#34; n为:299或更少&#34;。
答案 0 :(得分:1)
您最好使用AtomicInteger。
此问题将为您提供说明和示例:Practical uses for AtomicInteger
答案 1 :(得分:1)
我改变了你的代码:
private static final int NTHREADS = 300;
private static AtomicInteger n = new AtomicInteger();
public static void main(String[] argv) throws InterruptedException {
final CountDownLatch cdl = new CountDownLatch(NTHREADS);
for (int i = 0; i < NTHREADS; i++) {
new Thread(new Runnable() {
public void run() {
n.incrementAndGet();
cdl.countDown();
}
}).start();
}
cdl.await();
System.out.println("fxxk, n is: " + n);
}
你必须应对比赛条件。所有300个线程同时修改n
。例如:如果两个线程同时读取并递增n
,则将n
增加到相同的值。
这就是n
并非总是300
的原因,在这种情况下你输了一个增量。这种情况可能发生过零次或多次。
我将n
从int
更改为AtomicInteger
,这是线程安全的。现在一切都按预期工作了。
答案 2 :(得分:0)
静态上下文需要锁定类而不是Object。如果需要一个静态变量进行同步,并且不需要将其缓存在本地线程中,则需要将其声明为volatile。
答案 3 :(得分:0)
public class ThreadsDemo {
public static int n = 0;
private static final int NTHREADS = 30;
public static void main(String[] argv) throws InterruptedException {
final CountDownLatch cdl = new CountDownLatch(NTHREADS);
for (int i = 0; i < NTHREADS; i++) {
new Thread(new Runnable() {
public void run() {
for (int j = 0; j < 1000; j++) // run a long time duration
n += 1;
cdl.countDown();
}
}).start();
}
cdl.await();
System.out.println("fxxk, n is: " + n);
}
}
输出“n是:29953” 我认为原因是,线程运行的持续时间很短,并且jvm不会进行上下文切换。
答案 4 :(得分:-1)
Java静态字段将在线程之间同步吗?
没有。您应该将其设为volatile
或同步对其的所有访问权限,具体取决于您的使用模式。