在看java并发编程实战的时候遇到了一些问题..讨教大家一下…很基础的…谢谢大家了
1.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指令重排"); } } }
应该是可见的吧? 假如本人看书没有理解错….
2.书上有个例子本人一直没搞懂..
本人的问题是:本人觉得这个异常不可能会出现呀….
n != n 这个操作虽然不是原子的,可能要读取2次n,再做1次比较…
但是这是在调用assertSanity的时候才会做的…调用对象的方法的时候不是会把指向对象的引用传到方法中吗…这样的话虽然线程2可以修改holder指向其他对象,但是线程1调用assertSanity的时候传入的指针始终指向的是前面那个对象..所以本人觉得2个n要么都等于0,要么都等于42,不会1个等于0,1个等于42呀…
求高手解惑…谢谢了
解决方案
100
你循环里面只有2个线程,执行完就结束了。每次循环VolatileTest5都是new 了一个的。其实吧,就算写到外面,你先看到结果也很难,速度太快了。