在第66条(同步访问共享的可变数据)中作者写的第一个例子——那个永远不会终止的例子,为什么在我的机器里却是每次都执行了一秒之后就自动终止了呢?我机器的java版本是javase-1.6,用的eclipse开发工具

解决方案 »

  1.   

    ok,我贴上代码:
    import java.util.concurrent.TimeUnit;
    public class StopThread {
    private static boolean stopRequested;
    public static void main( String[] args ) throws InterruptedException{
    Thread backgroudThread = new Thread( new Runnable(){
    public void run() {
    int i = 0;
    while ( !stopRequested )
    {
    i++;
    }
    }
    });

    backgroudThread.start();

    TimeUnit.SECONDS.sleep( 1 );
    stopRequested = true;
    System.out.print( "as" );
    }
    }
      

  2.   

    看了一下原文,作者的意思是这样的写法不好,在他的机器上出了问题。应该用同步写才比较好。“
    On my machine, however, the program never terminates: the background
    thread loops forever!
      

  3.   

    有这样一句话“This optimization is known as hoisting, and it is precisely what the HotSpot server VM does.“。所以可能是您的是HotSpot client。您打个"java -version"看看您的版本。
      

  4.   

    从代码上看不出任何问题,也许可JVM的优化有关。
      

  5.   

    仔细看item66的话也说得比较清楚了
    线程之间如果未同步是有可能造成关于stopRequested变量不及时共享的
      

  6.   

    The problem is that in the absence of synchronization, there is no guarantee as
    to when, if ever, the background thread will see the change in the value of stop-
    Requested that was made by the main thread. In the absence of synchronization,
    it’s quite acceptable for the virtual machine to transform this code:while (!done){
        i++;
    }into this code:if (!done) {
        while (true){
            i++;
        }
    }
    This optimization is known as hoisting, and it is precisely what the HotSpot server
    VM does. The result is a liveness failure: the program fails to make progress. One
    way to fix the problem is to synchronize access to the stopRequested field.
      

  7.   

    JDK 1.5 或以上版本的话,在共享变量上加上 volatile 关键字就可以得到保证了。JDK 1.5 以下的版本这样改了也没用,必须使用同步方法或者同步代码块。private volatile static boolean stopRequested;volatile 能保证共享变量的值不从线程栈中获取缓存的数据。
      

  8.   

    正是这样的问题——JMM(Java 内存模型)不严谨的规定,导致在 JDK 1.5 以下版本中用于单例的双检锁模式是无效的,因为在不带同步访问共享变量来说,一个线程更改了其变量的值,另一个线程并不会立即看到值的更改。关于这个问题最著名的一篇文章:The "Double-Checked Locking is Broken" Declaration 
    http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
      

  9.   

    这篇文章真挺好的,有些地方都很简练地说明和总结了double-checked locking这个现象
    关于why it doesn't work
    The first reason it doesn't workThe most obvious reason it doesn't work it that the writes that initialize the Helper object and the write to the helper field can be done or perceived out of order. Thus, a thread which invokes getHelper() could see a non-null reference to a helper object, but see the default values for fields of the helper object, rather than the values set in the constructor.If the compiler inlines the call to the constructor, then the writes that initialize the object and the write to the helper field can be freely reordered if the compiler can prove that the constructor cannot throw an exception or perform synchronization.Even if the compiler does not reorder those writes, on a multiprocessor the processor or the memory system may reorder those writes, as perceived by a thread running on another processor. 他这里只是提到关于constructor的Out-of-order writes现象,还是没有点到为什么最终得到的会是那个为构建的只有默认值的对象non-null reference,虽然可能也不是太难想到~此时另外一个线程却可以得到一个非空未初始化对象,下面这个链接有较详细说明:http://www.ibm.com/developerworks/java/library/j-dcl.html
      

  10.   

    主要是取决于jvm的优化,作者说的情况是下面这种(模拟作者jvm优化后的效果),这样第一个线程只会判断一次标志位,所以控制不了
    public class Test0702 { private static boolean stop;
    /**
     * @param args
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException {
    // TODO Auto-generated method stub
    Thread bt = new Thread(new Runnable(){ public void run() {
    // TODO Auto-generated method stub
    int i=0;
    // while(!stop)
    // {
    // i++;
    // System.out.println(i);
    // }
    if(!stop)
    while(true) 
    {
    i++;
    System.out.println(i);
    }
    }

    });

    bt.start();
    java.util.concurrent.TimeUnit.SECONDS.sleep(1);
    stop = true;
    }}