关于synchronized是否能保证可见性。

在文章http://blog.csdn.net/taotao4/article/details/42744871中有验证过volatile可见性,早上起来觉得java中常用的同步关键字synchronized没有明确提过是否能保证可见性。猜测synchronized关键字,不能作为可见性的保证,于是修改了上一篇博客的代码验证一下,只是在t1线程中增加了synchronized关键字

代码如下:

 

package com.easy;
public class Main {
	
	public static Integer max = 100;
	
	public static void main(String[] args){
		Thread[] threads = new Thread[20];
		
		for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    
                    while (true) {
                    	if(max == null ){
                    		max = 10;
                    		System.out.println("已经被重置为null");
                    	}
                    }
                }
            });
            threads[i].start();
        }
		
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		Thread t1 = new Thread(){
			public void run(){
				while(true){
//					System.out.println("重置中");
					synchronized(this){
					max = null;
					}
				}
			}
		};
		t1.start();
	}
}
代码的执行结果是永远看不到“已经被重置”这段话的输出。也就是后面t1线程max=null的结果,对上面thread[i]中每一个线程都不可见。

再次引用文章:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#incorrectlySync

这里提到synchronized会保证对进入同一个监视器的线程保证可见性。比如线程th1修改了变量,退出监视器之前,会把修改变量值v1刷新的主内存当中;当线程t2进入这个监视器时,如果有某个处理器缓存了变量v1,首先缓存失效,然后必须重主内存重新加载变量值v1(这点和volatile很像)。这里语义的解读只是说了对于同一个监视器,变量的可见性有一定的方式可寻,非同一个监视器就不保证了。


本文的代码示例不符合同一个监视器的条件,所以有这不可见也就正常了。

测试平台:

os x 10.10.2 

cpu i5

java version "1.7.0_71"

Java(TM) SE Runtime Environment (build 1.7.0_71-b14)

Java HotSpot(TM) 64-Bit Server VM (build 24.71-b01, mixed mode)



你可能感兴趣的:(java,synchronized,可见性,多线程)