请举个例子, 不使用 volatile 关键字时, 结果是不稳定的,使用volatile时,结果是不稳定的
不要说明, 只要一段简短的java代码来说明只有使用 volatile 关键字时才能达到预期的目标

解决方案 »

  1.   

    public class Counter_ThreadSafe {
        public int getCount(){
            return _count;
        }
        public synchronized void count(){
            ++_count;
        }
        private volatile int _count=0;
    }////由此不同线程调用每次调用getCount() 都会得到正确计数值。
    ////不过这个例子似乎不是很好。因为必须对count加synchronized
      

  2.   

    这个修饰符应该表示变量是线程安全的吧   
      你写两个或多个线程,并发访问同一个volatile的变量i   
      例如在run里面:   
      if(i>0)   
      {   
          Thread,.sleep(10);   
          System.out.println(i--);   
      }   
      如果某个线程的输出为0甚至是负数,则说明你的程序不是线程安全的   
        但是加了volatile修饰应该就不会有这种情况发生 
      

  3.   

    通过测试二楼的代码, 发现结果很不稳定, 与没有volatile修饰符结果是一样的,代码如下:import java.util.Random;public class Counter_ThreadSafe {    public int getCount(){ 
            return _count; 
        } 
        public synchronized void count(){ 
            ++_count; 
        } 
        private volatile int _count=0;  public static void main(String[] args) throws InterruptedException {
    final Counter_ThreadSafe c = new Counter_ThreadSafe();
    final Random rand = new Random();
    for (int i = 0; i < 100; i++) {
    Thread.sleep(0);
    new Thread(new Runnable() {
    public void run() {
    try {
    c.count();
    Thread.sleep(rand.nextInt() % 2 + 2);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    System.out.println(c.getCount());
    }
    }).start();
    }
    }
    }测试三楼的代码, 加不加volatile 都会有负数的情况发生, 代码如下:import java.util.Random;public class Counter_ThreadSafe { private static volatile int i = 7; private void count() throws InterruptedException {
    if(i>0)    
    {    
    Thread.sleep(10);    
    System.out.println(i--);    

    } public static void main(String[] args) throws InterruptedException {
    final Counter_ThreadSafe c = new Counter_ThreadSafe();
    final Random rand = new Random();
    for (int i = 0; i < 100; i++) {
    Thread.sleep(0);
    new Thread(new Runnable() {
    public void run() {
    try {
    c.count();
    Thread.sleep(rand.nextInt() % 2 + 2);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    //System.out.println(c.getCount());
    }
    }).start();
    }
    }
    }
      

  4.   

    请举个例子, 不使用 volatile 关键字时, 结果是不稳定的,使用volatile时,结果是稳定的 使用volatile时,结果是稳定的, 发贴时写成不稳定了, 不好意思, ```当时太急了``
      

  5.   

    只接触过一次,是在学习线程安全的Singleton模式的时候学的
      

  6.   

    楼主的样例代码犯了与3楼朋友同一个毛病。
    我把三楼的代码再贴一下:if(i>0)    
      {    
          Thread,.sleep(10);    
          System.out.println(i--);    
      }    
    这里很明显无法表现出volatile的功效。因为比如说当前i为1,i>0成立,那么接下去操作。碰到sleep()之后切换线程,i的值很有后可能被其它线程修改,这很正常。我想说的是,在Java中,volatile很难测试。因为在C/C++中测也不是很容易,还要设置编译选项,开启代码优化才可能发现volatile的功效。
    volatile字面意思是“不稳定的,易挥发的”。也就是说其值将受到外部的改变。在C/C++中,由于使用机器的寄存器,所以变量的值将会保存在寄存器中,比如以下代码:while(i > 0)
    {
        i--;
    }i的值很有可能被放入寄存器(这里也很有可能被放在循环计数寄存器中),这样在这个循环中,i 所在地址的内容可能不会一下子受到改变,改变的只是寄存器中的值。如果给他加以volatile修饰的话,那么每次做“i--”的时候,总要访问i 的地址,对于内容进行减1操作(尽管这可能会在Cache中)。不过即使是访问Cache,其速度也不会有寄存器那么快。
    所以,在目前Java环境下测volatile比较困难,目前的环境也没有提供非常完善的代码调试工具,也就是说不公开Java虚拟机指令集。至少在Eclipse上没有,不知道在NetBeans上怎么样。不过即使要发挥volatile,那么也只能依靠JIT技术了。让Java字节码及时地转为本地机器指令码进行运行,只有这样才有可能看到效果,而且转换后的机器二进制码又要是经过一定优化的,也就是不用volatile修饰的变量尽可能的使用寄存器。
    所以楼主也不要怪二楼、三楼,先不看你的测试代码,本身的测试环境也是有限的。