synchronized和volatile解决线程可见性

java多线程开发中,控制共享数据比较麻烦,有可见性和同步性。通常控制可见性咱们能够经过synchronized和volatile控制,而同步性咱们只能经过synchronized或Lock来控制。java

我喜欢经过对一个问题的理解,来理解某个知识点,由于我以为知识就是为了解决问题。多线程

public class SynchronizedTest {
	
	private static boolean flag = true;
	

	public static void main(String[] args) throws Exception{

		new Thread(new Runnable() {
			@Override
			public void run() {
				while(flag) {
					
				}
				System.out.println("子线程执行结束================");
			}
		}).start();
		
		Thread.sleep(1000);
		
		flag = false; // 关闭线程输出
		System.out.println("flag已被修改成false");
	}

}

上面的代码在64位JVM机器(准确来讲应该是jvm的server模式)上执行通常都不会输出“子线程执行结束================”,而在32位的jvm的client模式下却能够输出“子线程执行结束================”。jvm

经过 java -version 能够查看本身本机jvm运行的模式。ide

注意:若是你的jvm装的是64位,那么是没法切换到client模式的。优化

上面的问题引发的缘由其实就是因为java的内存模型引发的,java内存模型中分有主内存和工做内存之分,主内存能够理解为共享数据的区域(不知道准确不许确),而工做内存(主内存数据的副本)是每一个线程私有的一块区域,每一个线程对共享数据的修改,不会直接操做共享数据,通常是先修改工做内存中的数据,而后在某个特定的时候刷新到主存,其余线程才有机会看到其修改。this

解决以上问题线程

  1. 能够将flag前加上volatile关键字。

private static volatile boolean flag = true;code

缘由:能够这么简单理解,加了volatile关键字的共享变量,全部线程对其值的获取或修改都直接经过主存,绕过来工做内存,因此主线程对flag的修改子线程立刻就能够看到。server

volatile的原理就是加内存屏障,全部的读都在写以后,这样保证了子线程对flag的访问在主线程对flag的修改以后。对象

  1. 可使用synchronized
new Thread(new Runnable() {
	@Override
	public void run() {
		int count = 0;
		while(flag) {
			synchronized(SynchronizedTest.class){ //这里能够锁任何共享对象
				count++;
			}		
		}
		System.out.println("子线程执行结束================");
	}
}).start();

上面之因此加上 count ,是防止JIT优化将无用的锁代码块优化掉。

缘由:因为jvm规定在进入synchronized以前会将全部其余线程的工做内存刷新到主存(这个我不太肯定是否正确,若是有肯定的请留言告诉我,谢谢),在离开synchronized块以前会将本线程的工做内存刷新到主内存。

在验证这个之中我踩过一个坑,个人代码以下:

new Thread(new Runnable() {
	@Override
	public void run() {
		while(flag) {
			System.out.println("====falg=====");	
		}
		System.out.println("子线程执行结束================");
	}
}).start();

这样在任何状况下均可以输出"子线程执行结束================",找了好久才发现原来 System.out.println 方法中有synchronized同步块致使。

这个方法来自 System.out

public void println(String x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }

之中有很多观点是我本身的观点,可能不许确,或是错误的,但愿大家能给我指出,谢谢。

相关文章
相关标签/搜索