使用和不使用volatile进行实施

时间:2015-10-31 16:48:09

标签: java multithreading

我在代码下面运行:

import java.util.*;

public class Common_variable extends Thread{
    private boolean running = true;

    public void run()
    {
        while(running)
        {
            try {
                System.out.println("Hello");
                Thread.sleep(100);
            } catch (InterruptedException ex) {
               System.out.println(ex);
            }
        }
    }

    public void shutdown()
    {
      running = false;
    }
}

public class Thread_demo{

   public static void main(String args[])
   {
     Common_variable x = new Common_variable();
     x.start();

     Scanner in = new Scanner(System.in);
     in.nextLine();

     x.shutdown();
   }
}

现在,我有一些疑问。 当我们做" Common_variable x = new Common_variable();"时,创建新线程,这意味着单独的堆栈。那时,一个对象x也在堆中创建。我怀疑是:

是否只有#34;运行"的单一副本变量或新线程在其堆栈中也有一个?如果是,则两个线程如何能够相互通信并更新"运行"。如果没有,并且两者都从相同的内存位置访问,那么如果我们将变量运行为volatile,则会有什么不同。

请澄清我的理解错误。

2 个答案:

答案 0 :(得分:2)

这与线程堆栈无关。 running是对象的字段,因此存储在堆中。

但是由于多核计算机上的性能优化,每个核心都可以在其缓存中拥有此值的副本:访问缓存比访问主内存更快。

没有volatile,当主线程将标志设置为false时,无法保证其他线程会看到该更改:缓存的值不会被写入主内存,并且线程赢了&# 39;从主存储器重新读取它。

volatile保证对变量的每次更改都写入主内存,并且在该更改之后每次读取变量都会从主内存中重新读取。

那就是说,你应该优先选择AtomicBoolean而不是volatile变量。在这种情况下,您甚至根本不需要变量:每个线程都有一个中断标志,您可以通过interrupting the thread进行更改。这种内在机制的优点是,一旦线程被中断,线程就不会保持睡眠状态:它会立即退出sleep()方法,抛出InterruptedException,这将允许你立即停止线程。

答案 1 :(得分:1)

  

当我们做“Common_variable x = new Common_variable();”

不,当您拨打start()时会创建单独的堆栈。

您只创建了一个Common_variable对象,并且它有一个名为running的实例变量,因此如果您将此对象传递给各个线程,它们将共享running实例变量,可能会导致数据损坏,这就是我们使用同步来防止数据损坏的原因。

至于volatile,它保证了线程变量变化的可见性

请阅读此内容以获取更多http://tutorials.jenkov.com/java-concurrency/volatile.html