【java并发编程】关于sychronized可见性

public class T {
	/*volatile*/ boolean running=true;
	void m() {
		System.out.println("m start");
		while(running) {
			
		}
		System.out.println("m end");
	}
	public static void main(String args[]) {
		T t =new T();
		new Thread(()->t.m(),"t1").start();
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		t.running=false;
	}

这样一段话并不会使t1线程终止,因为java内存模型,每一个线程都拥有一个工作内存,其内部存储了主内存变量的副本,在主内存中修改了running的值,t1线程并不知道,他工作内存中running副本的值还未改变。

这个问题可以使用volatile来解决。

那么,sychronized呢?

当ThreadA释放锁M时,它所写过的变量(比如,x和y,存在它工作内存中的)都会同步到主存中,而当ThreadB在申请同一个锁M时,ThreadB的工作内存会被设置为无效,然后ThreadB会重新从主存中加载它要访问的变量到它的工作内存中。

也就是说,synchronized 只会保证该同步块中的变量的可见性,发生变化后立即同步到主存。另一个线程在申请锁的时候,会重新更新工作内存。

public class T {
	/*volatile*/ boolean running=true;
	synchronized void m() {
		System.out.println("m start");
		while(running) {
			
		}
		System.out.println("m end");
	}
	public static void main(String args[]) {
		T t =new T();
		new Thread(()->t.m(),"t1").start();
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		t.running=false;

	}
}

这样还是不可以的,因为sychronied修饰的代码块中并没有改写running变量。

但是,当我在循环里里面加了一个打印输出的语句,就可以终止线程了,为什么呢?

public class T {
	/*volatile*/ boolean running=true;
	void m() {
		System.out.println("m start");
		while(running) {
			System.out.println("2");
		}
		System.out.println("m end");
	}
	public static void main(String args[]) {
		T t =new T();
		new Thread(()->t.m(),"t1").start();
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		t.running=false;

	}
}

实际上,JVM对于现代的机器做了最大程度的优化,也就是说,最大程度的保障了线程和主存之间的及时的同步,也就是相当于虚拟机尽可能的帮我们加了个volatile,但是,当CPU被一直占用的时候,同步就会出现不及时,也就出现了后台线程一直不结束的情况。

也就是说,在cpu空闲的时候,可能会更新一下主内存的内容。

比如,我们在循环中sleep一下,亦可以结束线程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值