为什么使用了volatile关键字,两个线程还是没有同步成功!求救
public class TestVolatile implements Runnable {
private volatile int i = 0; @Override
public void run() {
while (i < 10) {
if ("bbb".equals(Thread.currentThread().getName()) && i == 3) {
i = 11;
}
System.out.println("hello world! " + i + " time(s)");
i++; try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public static void main(String[] args) {
Thread t1 = new Thread(new TestVolatile());
Thread t2 = new Thread(new TestVolatile());
t1.setName("aaa");
t2.setName("bbb");
t1.start();
t2.start();
}
}

解决方案 »

  1.   

    volatile 只保证可见行 没有保证原子性 i++ 有读取i 设置i 赋值i组成
      

  2.   

    i递增期间没有保证原子性这点能理解
    但是在i递增10次这段时间内,难道都没有一次去同步吗?
    如果没有一次去同步,那么volatile这个关键字到底是约束什么的。
      

  3.   

    另外说到可见性,当bbb线程改变i值后,那么aaa线程应该可以看到i已经大于10,但是实验结果是aaa线程继续走完
      

  4.   

    volatile
    保證變量的賦值過程是原子性,但不是保證線程同步
      

  5.   

    4楼说得对
    volatile保证的赋值过程是原子性的
    因为JAVA不能像C一样,确保赋值过程是原子的,所以要加volatile
      

  6.   

    对于volatile这个关键字,我不懂,连Core Java书中也写得不是很清楚。
    我给出另一种解决方法,可以把i作为临界区,凡是用到i的地方都要互斥使用,这样就能实现同步了public class TestVolatile implements Runnable 
    {
        private static int i = 0;
        private static Object obj = new Object();    public void run() 
        {
         int tmp;
         synchronized(obj)
         {
         tmp = i;
         i++;
         }
            while (tmp < 10) 
            {
                if ("bbb".equals(Thread.currentThread().getName()) && tmp == 3) 
                {
                 synchronized(obj)
                 {
                 i = 11;
                 tmp = i;
                 }
                }
                System.out.println("hello world! " + tmp + " time(s) " + Thread.currentThread().getName());
                synchronized(obj)
                {
                 tmp = i;
                 i++;
                }            try 
                {
                    Thread.sleep(1000);
                }
                catch (InterruptedException e) 
                {
                    e.printStackTrace();
                }
            }
        }    public static void main(String[] args) 
        {
            Thread t1 = new Thread(new TestVolatile());
            Thread t2 = new Thread(new TestVolatile());
            t1.setName("aaa");
            t2.setName("bbb");
            t1.start();
            t2.start();
        }
    }
      

  7.   

    楼上兄台的热情不胜感激,其实不用这么复杂,是要将i的修饰关键字换成static效果就是我要的,如果用synchronized也没有问题但是我就是要用volatile,但是实验结果不对,前面几位解释的我也看了,有点理解,不过还是求volatile进一步解释
      

  8.   

        volatile的作用是保证编译器读取这个变量的时候每次都到内存中去读取,而不是寄存器(因为有多个线程都在对这个变量进行读写,如果不加这种限制可能就会造成读写不同步)。但是从哪里读取变量和是否多线程同步是没有直接联系的,所以说volatile并不能保证线程同步。
        如果想让多线程同步要用synchronized关键字才行。
      

  9.   

    你的JDK 按本 是多少的tingking in java 指出 volatile 的JDK 版本 至少要在 5.0 以上
      

  10.   

    使用 AtomicInteger
    ibm的developerworks网站有几篇关于volitile的文章去看看就明白了。
      

  11.   

    volatile 保证变量只有一个副本,所有线程看到的都是同样的值
      

  12.   

    public static void main(String[] args) {
            Thread t1 = new Thread(new TestVolatile());
            Thread t2 = new Thread(new TestVolatile());

            t1.setName("aaa");
            t2.setName("bbb");
            t1.start();
            t2.start();
        }楼主注意这段程序, 这是在每一个线程中都分别创建了一个对象, 两个线程访问的是两个不同的对象,并且变量又不是静态的, 何来同步的问题。
      

  13.   


    我最近也在研究这个关键字的使用,貌似没有办法测试它。如果不加volatile这个关键字的话只是说可能会发生问题,但是在java里面几率很小很小, 我试过很多种情况都测不出来, 所以我认为在java里面应该是可以忽略了。我问过做C++的同事,他们说这种情况在c++里面比较常见, java里面就可以不计了。
      

  14.   

    你用两个不同的TestVolatile对象创建线程,怎么可能同步呢?
      Thread t1 = new Thread(new TestVolatile());
      Thread t2 = new Thread(new TestVolatile());应该改为
      TestVolatile t= new TestVolatile()
      Thread t1 = new Thread(t);
      Thread t2 = new Thread(t);
    这样用同一个TestVolatile 对象去创建两个线程才能同步
      

  15.   

    private volatile int i = 0;要设成静态的static
    volatile是线程属性共享,而不是对象属性共享
      

  16.   

    volatile对于一个操作是原子的,但是对于多个步骤是由程序决定的