java中的volatile关键字对于其他线程是不可见的,下面是我的代码

时间:2014-09-02 14:41:24

标签: java multithreading

当我在线程i中更新T1的值时,线程T2看不到该值 - 为什么?理论上volatile变量必须检索新值,但它不起作用。

    class Threads implements Runnable
    {

      public volatile int i=4;
      volatile int j=0;
      int x=0;

      public static void main(String[] args) {
        Threads th=new Threads();
        Thread a = new Thread(th);
        Thread b=new Thread(th);
        a.setName("T1");
        a.setPriority(Thread.MAX_PRIORITY);
        b.setName("T2");
        a.start();
        b.start();
      }

      public int count() {
        return ++i;
      }

      public void run() {
        while(j<=10)
        {

          if(Thread.currentThread().getName().equals("T1"))
          {
            i++;
            System.out.println(Thread.currentThread().getName()+" : "+i);

           try
           {
             Thread.sleep(2);
           }catch(Exception ex){}
         }
         else if(Thread.currentThread().getName().equals("T2"))
         {

           System.out.println(Thread.currentThread().getName()+" : "+i);
           try
           {
             Thread.sleep(1);
           }catch(Exception ex){}
         }

         j++;
       }
      }
    }

2 个答案:

答案 0 :(得分:1)

我不知道您希望代码输出的内容,但是:

请注意,即使变量是易变的,x++也是x = x + 1的快捷方式。它不是原子的,并且执行单独的读写操作,这两个操作之间的另一个线程可能会改变该值。

在您的情况下,对于变量i,只有一个线程正在编写变量,所以它不应该是一个问题。

但对于j,两个线程在同一个变量上执行j++。对于某些迭代,有可能一个线程在另一个线程的读写之间写入j。导致先前的写入被忽略。

要避免这种情况,您可以:

  • 执行j++区块中的synchronized
  • 使用AtomicInteger代替volatile int

另一点是j <= 10上的测试是在增量之前完成的。因此,当while时,两个线程可以输入j==10进行迭代,从而导致j==12结束(或者当涉及上述效果时也会有不同的东西)。

要解决此问题,您可以使用while直接在AtomicInteger条件中增加:

while(j.getAndIncrement() <= 10)

答案 1 :(得分:0)

您正在从每个线程实例访问本地i - 您的每个线程对象都有自己的i,j,x实例,并且您没有交叉引用它们。

实际上你的线程甚至都不知道那里还有其他线程。