简体   繁体   English

Java中的volatile关键字对其他线程不可见,这是我的代码

[英]volatile keyword in java is not visible to other threads below is my code

When I update the value of i in thread T1 , the value is not visible to thread T2 - why? 当我在线程T1更新i的值时,该值对于线程T2不可见-为什么? Theoretically volatile variables must retrieve fresh values, but it is not working. 从理论上讲, 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++;
       }
      }
    }

I don't know what you expect your code to output, but: 我不知道您期望代码输出什么,但是:

Note that even if a variable is volatile, x++ is a shortcut for x = x + 1 . 请注意,即使变量是volatile, x++也是x = x + 1的快捷方式。 It is not atomic, and performs separate read and write operations, the value may be changed by another thread between the two operations. 它不是原子的,并且执行单独的读取和写入操作,该值可以由两个操作之间的另一个线程更改。

In your case, for variable i , only one thread is writing the variable, so it should not be an issue. 在您的情况下,对于变量i ,只有一个线程正在写入该变量,因此这不是问题。

But for j , two threads are doing j++ on the same variable. 但是对于j ,两个线程在同一个变量上执行j++ There is probability that, for some iterations, one thread writes j between the read and write of the other thread. 对于某些迭代,一个线程有可能在另一线程的读写之间写入j Resulting in the earlier write to be ignored. 导致较早的写入被忽略。

to avoid this, you can either: 为避免这种情况,您可以:

  • do the j++ in a synchronized block synchronized块中执行j++
  • use AtomicInteger instead of volatile int 使用AtomicInteger而不是volatile int

Another point is that the test on j <= 10 is done before the increment. 另一点是,对j <= 10的测试是在递增之前完成的。 So the two threads may enter the while for an iteration when j==10 , resulting in the end by having j==12 (or even something different when the effect described above is also involved). 因此,当j==10 ,两个线程可能会进入while进行迭代,结果是j==12 (或者在涉及上述效果时甚至有所不同)。

To solve that, you may increment directly in the while condition, using an AtomicInteger for instance: 为了解决这个问题,您可以在while条件下直接增加,例如使用AtomicInteger

while(j.getAndIncrement() <= 10)

You are accessing the local i from each thread instance - each of your thread objects has their own i, j , x instances and you are not cross referencing them. 您正在从每个线程实例访问本地i-每个线程对象都有自己的i,j和x实例,并且您没有交叉引用它们。

Actually your threads do not even know that there are any other threads out there. 实际上,您的线程甚至都不知道那里还有其他线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM