java静态字段会在线程之间同步吗?

时间:2017-04-28 05:33:54

标签: java multithreading synchronization

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;。

5 个答案:

答案 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的原因,在这种情况下你输了一个增量。这种情况可能发生过零次或多次。

我将nint更改为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或同步对其的所有访问权限,具体取决于您的使用模式。

相关问题