java volatile的一些疑问(基础)

J2EE 码拜 9年前 (2016-03-19) 1098次浏览
在看java并发编程实战的时候遇到了一些问题..讨教大家一下…很基础的…谢谢大家了java volatile的一些疑问(基础)
1.volatile修饰了一个对象以后,这个对象的属性对其他线程也是可见的吗?
举例:

public class VolatileTest {
    volatile boolean b = false;
    int a = 0;
    public static void main(String[] args) {
        for (int i=0; i<10000000; i++) {
            VolatileTest resource = new VolatileTest();
            Thread t1 = new Thread(new A(resource));
            Thread t2 = new Thread(new B(resource));
            t1.start();
            t2.start();
        }
    }
}
class A implements Runnable {
    volatile VolatileTest r = null;
    public A(VolatileTest a) {
        r = a;
    }
    public void run() {
        r.a = 1;
        r.b = true;
    }
}
class B implements Runnable {
	volatile VolatileTest r = null;
    public B(VolatileTest a) {
        r = a;
    }
    public void run() {
        while (!r.b) {
            Thread.yield();
        }
        int temp = r.a;
        if (temp == 0) {
            System.out.println("出现CPU指令重排序");
        }
    }
}

这个例子中不会打印打印语句,原因是b前面加了volatile关键字.
那假如修改这个例子为以下这样,那会打印吗? volatile修饰了1个对象,这个对象的全部属性也会对其他线程可见?

public class VolatileTest5 {
    volatile VolatileTest5_Resource resource = new VolatileTest5_Resource();
    public static void main(String[] args) {
        for (int i=0; i<10000000; i++) {
            VolatileTest5 v = new VolatileTest5();
            Thread t1 = new Thread(new VolatileTest5_A(v));
            Thread t2 = new Thread(new VolatileTest5_B(v));
            t1.start();
            t2.start();
        }
    }
}
class VolatileTest5_Resource {
    boolean b = false;
    int a = 0;
}
class VolatileTest5_A implements Runnable {
    volatile VolatileTest5 r = null;
    public VolatileTest5_A(VolatileTest5 a) {
        r = a;
    }
    public void run() {
        r.resource.a = 1;
        r.resource.b = true;
    }
}
class VolatileTest5_B implements Runnable {
    volatile VolatileTest5 r = null;
    public VolatileTest5_B(VolatileTest5 a) {
        r = a;
    }
    public void run() {
        while (!r.resource.b) {
            Thread.yield();
        }
        int temp = r.resource.a;
        if (temp == 0) {
            System.out.println("出现CPU指令重排");
        }
    }
}

应该是可见的吧? 假如本人看书没有理解错….
java volatile的一些疑问(基础)
2.书上有个例子本人一直没搞懂..
java volatile的一些疑问(基础)
java volatile的一些疑问(基础)
本人的问题是:本人觉得这个异常不可能会出现呀….
n != n 这个操作虽然不是原子的,可能要读取2次n,再做1次比较…
但是这是在调用assertSanity的时候才会做的…调用对象的方法的时候不是会把指向对象的引用传到方法中吗…这样的话虽然线程2可以修改holder指向其他对象,但是线程1调用assertSanity的时候传入的指针始终指向的是前面那个对象..所以本人觉得2个n要么都等于0,要么都等于42,不会1个等于0,1个等于42呀…
求高手解惑…谢谢了java volatile的一些疑问(基础)

解决方案

100

引用

VolatileTest5 v = new VolatileTest5();
Thread t1 = new Thread(new VolatileTest5_A(v));
Thread t2 = new Thread(new VolatileTest5_B(v));
t1.start();
t2.start();

你循环里面只有2个线程,执行完就结束了。每次循环VolatileTest5都是new 了一个的。其实吧,就算写到外面,你先看到结果也很难,速度太快了。


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明java volatile的一些疑问(基础)
喜欢 (0)
[1034331897@qq.com]
分享 (0)