synchronized和lock保证的可见性

21 篇文章 0 订阅

我们知道volatile关键字能够禁止指令重排序并保证可见性,但在我们平时使用共享容器时,好像并没有使用volatile关键字,仅仅使用了synchronized或者lock锁,没有产生可见性问题,那么这两种锁是如何保证有序性的?

synchronized

在进入synchronized锁时,会去主存中读取此时的最新数据,退出锁时将当前更新刷新到主存中。
synchronized不会禁止重排序,因为重排序会保证不改变单线程下的程序运行结果,synchronized将同步变为了串行操作,因此不会阻止指令重排序。但它会保证以下几点

  1. 锁内和锁外的排序不会乱,即在锁内的语句不会跑到锁外,锁外的语句也不会跑到锁内
  2. 锁外代码顺序以及锁内代码顺序仍有可能重排序
  3. 先执行锁内代码还是锁外代码也不一定

由于我们会将共享变量放在锁内执行,所以我们在进入锁时会拿到最新的数据,离开锁时刷新到主存。切由于锁是互斥的,在此期间也不会别的线程对共享变量进行修改,因此不会发生可见性问题。

public void test(v){
	synchronized(this){
		a = v.a//保证最新
	}
	b = v.b //较新的
	c = v.c //较新的
}
// 可能重排序成下面的
public void test(v){
	b = v.b //旧的
	synchronized(this){
		a = v.a//保证最新
	}
	c = v.c //较新的
}

要注意共享变量只能在锁内操作,锁保证的可见性是在进入锁的时候的最新数据,如果错误的在非同步块操作了共享数据,同样会导致不可见性。

Lock

lock的加锁和释放锁是对内部字段state的修改,而state是一个volatile修饰的变量
无论是加锁还是释放锁,都会读取state的值并进行CAS修改操作,由于volatile保证的全体可见性,在修改state时能够拿到最新的共享变量的值,并根据锁定义互斥性的只有一个线程获得操纵权,从而保证了可见性,获得锁的线程拿到的一定是最新的数据。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值