Java volatile变量的行为不正确。 [英] Java volatile variable doesn't behave correctly.

查看:99
本文介绍了Java volatile变量的行为不正确。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

public class MyThread
{
    volatile static int i;

    public static class myT extends Thread
    {
        public void run ()
        {
            int j = 0;
            while(j<1000000){
                i++;
                j++;
            }
        }
    }

    public static void main (String[] argv)
    throws InterruptedException{
            i = 0;

            Thread my1 = new myT();
            Thread my2 = new myT();
            my1.start();
            my2.start();

            my1.join();
            my2.join();

            System.out.println("i = "+i);
    }
}

由于在关系之前发生了不稳定的构建,因此最终值我应该严格2000000.但是,实际结果与变量i没有不变量没什么不同。任何人都可以解释为什么它在这里不起作用?由于i被声明为volatile,因此应该保护它不受内存不一致的影响。

Since volatile builds happens-before relationship, the final value of i should be strictly 2000000. However, the actual result is nothing different from being without volatile for variable i. Can anyone explanation why it doesn't work here? Since i is declared volatile, it should be protected from memory inconsistency.

推荐答案


任何人都可以解释为什么它在这里不起作用?由于我被声明为volatile,因此应该保护它不受内存不一致的影响。

Can anyone explanation why it doesn't work here? Since i is declared volatile, it should be protected from memory inconsistency.

它受到保护但不幸的是 i ++ 不是原子操作。它实际上是读/增/存。所以 volatile 不会让你免于线程之间的竞争条件。您可以从程序中获得以下操作顺序:

It is protected but unfortunately i++ is not an atomic operation. It is actually read/increment/store. So volatile is not going to save you from the race conditions between threads. You might get the following order of operations from your program:


  1. 线程#1读取 i ,得到10

  2. 之后,第2号线读取 i ,得到10

  3. 线程#1增量 i 到11

  4. 线程#2增量 i 到11

  5. 线程#1将11存储到 i

  6. 线程#2将11存储到 i

  1. thread #1 reads i, gets 10
  2. right afterwards, thread #2 reads i, gets 10
  3. thread #1 increments i to 11
  4. thread #2 increments i to 11
  5. thread #1 stores 11 to i
  6. thread #2 stores 11 to i

正如您所看到的,即使已经发生了2次增量,值已在线程之间正确同步,竞争条件意味着该值仅上升1.请参阅漂亮的解释。这是另一个很好的答案: Java线程安全中的volatile int?

As you can see, even though 2 increments have happened and the value has been properly synchronized between threads, the race condition means the value only went up by 1. See this nice looking explanation. Here's another good answer: Is a volatile int in Java thread-safe?

你应该使用的是 AtomicInteger ,它允许你从多个线程安全地增加。

What you should be using are AtomicInteger which allows you to safely increment from multiple threads.

static final AtomicInteger i = new AtomicInteger(0);
...
        for (int j = 0; j<1000000; j++) {
            i.incrementAndGet();
        }

这篇关于Java volatile变量的行为不正确。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆