Java锁的迭代(synchronize篇)

Java锁的诞生

锁为什么需要,在多线程,高并发下,多个线程同时访问共享资源,都可以对共享资源做修改,很容易出现线程安全问题。

那什么是线程安全问题?

线程安全可以归于这些问题

多个线程同时修改一个变量,原子性、可见性,当然最主要的是操作系统对线程的调度是随机的

原子性是指,线程的一组操作是否是不可分割的,例如售票问题,一个售票机此时只有一张票,

但此时有两个线程,线程1和线程2同时进来看到还剩一张票,同时抢,但由于此时1线程在看到后,转而要去执行线程2,线程2去扣减票数后,又回来继续执行线程1的扣减,这样就会出现超卖

所以,线程不是原子的,就会出现线程安全问题

可见性问题

线程工作是有自己的工作空间的,所以线程之间是不可见的

科普一下

为了解决这样的问题,java有自己的内存模型(JMM)

内存模型的目标就是为了定义程序中变量的访问规则,定义java虚拟机将共享变量存到主内存中,从主内存中读取共享变量。

JMM有如下规定:

所有变量都存储在主内存中,每个线程都有自己的工作内存

工作内存中保存了被该线程使用的变量的副本,线程对变量的操作都应在自己的工作空间中进行,不能直接读写主内存

操作完成后,再通过内存一致性协议刷回主内存

所以,可见性问题就由此诞生,例如线程1对变量正在做修改,此时线程2读取变量,那么就会出现线程安全问题

指令重排

是指在程序运行时为了提高性能,编译器和处理器会对指令进行重排序,重排序

分为编译器优化的重排序、指令级并行的重排序、内存系统的重排序

但是,这些重排序,无论如何变化,都要保证结果和预期结果一致,也就是要遵循as-if-serial语义

而在指令重排情况下就会出现线程安全问题。

最开始java是使用synchronized同步互斥锁,且是重量级锁,效率低下

后来,在jdk1.6中,开发者发现大多数情况下锁并不存在竞争,一把锁往往是由一个线程来获取,所以推出了偏向锁

偏向锁:在每次线程获取锁时,只需要判断当前锁的资源是否是偏向自己的,如果是偏向自己的,就不需要额外的操作

偏向锁的申请流程为: 

他会查看在对象头的Mark Word是否标记为偏向锁,如果是偏向锁模式就会继续执行,不是就会升级到判断轻量级锁。

是偏向锁,会查看当前偏向锁记录的线程Id是否和当前操作的线程Id一致,如果一致就可以直接操作

如果不是就会利用cas算法将对象的Mark Word的线程ID修改为当前线程ID,修改成功,那便成功加上了偏向锁,如果修改失败,那就是有多线程争抢资源,升级为轻量级锁

轻量级锁:为了避免直接使用重量级锁,索带来的性能消耗

申请流程:

   首先,加锁对象如果没有被锁定,会在线程的栈帧中开辟一个所记录空间,记录对象Mark Word的拷贝,虚拟机使用cas算法将Mark Word 修改为指向锁记录空间的指针,

如果修改成功,则加锁成功,锁的标志位变为00,表示该线程已经加上轻量级锁

如果加锁失败,代表有多个线程在争抢资源,虚拟机会查看对象Mark Word 的指针是否指向当前线程的锁记录空间,如果是,则直接进入同步块执行,

如果不是则加锁失败,锁的标志位变为10,膨胀为重量级锁,同步阻塞执行

那么就会有人想了,既然我在jdk1.6中已经对synchronize关键字,这个同步锁优化升级了,那为什么java的sdk,也就是juc中还提供了Lock锁,这不是闲的吗?

事实上,synchronize仍然有他自己局限性

synchronize他是一个同步阻塞锁,是无法主动释放的,这很容易导致死锁问题,

发生死锁有四个状态(互斥条件、不可释放、请求与保持、循环等待

然而在大多数情况下,我们希望打破这个“不可释放”,我们希望在申请资源的时候希望,能够在申请不到的时候,主动释放资源,

于是我们又设计了一个锁,我们希望这把锁,可以

具备响应中断、支持超时、非阻塞这样的性质,所以我们,又有了juc包下的锁Lock

Lock锁的更多细节,请看下集

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

羊驼有点累

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值