首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > Java相关 >

Java volatile修饰符现实功能的疑问,大家看看为什么会这样

2013-06-25 
Java volatile修饰符实际功能的疑问,大家看看为什么会这样?本帖最后由 carrd2008 于 2013-05-30 12:51:58

Java volatile修饰符实际功能的疑问,大家看看为什么会这样?
本帖最后由 carrd2008 于 2013-05-30 12:51:58 编辑 public class ThreadTest implements Runnable {

String s;
volatile int c;

public ThreadTest(String s) {
this.s = s;
}

public void run() {
for (int i = 0; i < 10; i++) {
c ++;
System.out.println(this.s + ":" + c);
try {
if ("Thread1".equals(s)) {
Thread.sleep(500);
} else {
Thread.sleep(2000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) {
new Thread(new ThreadTest("Thread1")).start();
new Thread(new ThreadTest("Thread2")).start();
}

以上代码的某一次的执行结果是:
Thread1:1
Thread2:1
Thread1:2
Thread1:3
Thread1:4
Thread1:5
Thread2:2
Thread1:6
Thread1:7
Thread1:8
Thread2:3
Thread1:9
Thread1:10
Thread2:4
Thread2:5
Thread2:6
Thread2:7
Thread2:8
Thread2:9
Thread2:10

从结果看出,Thread1和Thread2这两个线程内部对变量c的运算没有互相影响。
也就是说,每次修改c,都没有跟主存进行同步。
而资料上说:volatile的功能是用于把工作内存中的副本同步到主存中,这样这个线程对变量的修改针对其他线程达到可视的效果。也就是变量共享。
但我的例子中,我用了volatile修饰符,但变量还是没有起到共享的目的。

请问这是为什么?
是我的例子写的有问题吗? Java 多线程 volatile
[解决办法]
2个线程运行2个不同的实例,内部变量c是不会影响的。


new Thread(new ThreadTest("Thread1")).start();
new Thread(new ThreadTest("Thread2")).start();


要么将
volatile int c;

改成static的
static volatile int c;


要么使用一个实例

package cn.sax.test;

public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        final ThreadTest t = new ThreadTest("");

        new Thread(t, "Thread1").start();
        new Thread(t, "Thread2").start();
    }

    static class ThreadTest implements Runnable {

        volatile int c;

        public ThreadTest(String s) {
        }

        public void run() {
            final String threadName = Thread.currentThread().getName();

            for (int i = 0; i < 10; i++) {


                c++;

                System.out.println(threadName + ":" + c);
                try {
                    if ("Thread1".equals(threadName)) {
                        Thread.sleep(500);
                    } else {
                        Thread.sleep(1000);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}



但是以上的修改还是有问题的
虽然增量操作(x++)看上去类似一个单独操作,实际上它是一个由读取-修改-写入操作序列组成的组合操作,必须以原子方式执行,而 volatile 不能提供必须的原子特性。实现正确的操作需要使 x 的值在操作期间保持不变,而 volatile 变量无法实现这点。

所以不赞成使用volatile进行累加,一般最好是用来改变boolean的数值。

热点排行