Java多线程~常见的锁策略(上)~乐观锁与悲观锁、读写锁、重量级锁与轻量级锁

目录

乐观锁与悲观锁

悲观锁

乐观锁

乐观锁好还是悲观锁好

读写锁

重量级锁与轻量级锁


乐观锁与悲观锁

悲观锁

以悲观的心态看待线程冲突问题,所以每次都加锁操作共享变量。总是假设最坏的情况发生,每次去拿数据的时候都认为其他线程会对其进行修改,因此每次在拿数据的时候都进行上锁操作,这样其他线程想拿到这个数据就会阻塞直到它拿到锁

乐观锁

假设数据一般情况下不会发生并发冲突,所以在数据进行提交更新的时候,才会正式对数据是否产生并发冲突进行检测,如果发现并发冲突,则返回用户错误的信息,让用户决定应该怎么处理。以乐观的心态看待线程冲突问题,所以每次都不加锁(层序层面),就直接操作共享变量。

乐观锁好还是悲观锁好

没有绝对的更好,不同的锁策略适用不同的场景,当大部分情况下存在线程冲突时,就使用悲观锁;当大部分情况下不存在线程冲突时,就使用乐观锁。

· 线程冲突:多个线程并发并行的对同一个共享变量进行操作(存在线程安全问题)

读写锁

多线程之间,如果是单纯的读操作,不会产生线程安全问题,但在多个线程进行写操作时、或者是

写操作与读操作之间就会产生线程安全问题,就需要进行互斥。如果两种场景下都用同一个锁,就会产生很大的性能的消耗,因此就引入了读写锁。

读写锁(readers-writer lock):从英文上来看,readers是复数,而writer是单数,说明在执行加锁操作时需要额外表明读写意图,复数读者之间不互斥,而写者需要与所有的读者、写者互斥.

一个线程对于数据的访问,主要就是读数据操作和写数据操作.

· 两个线程都是读取同一个数据,此时不存在线程安全问题,直接并发的读就可以

· 两个线程同时要写一个数据时,此时存在线程安全问题

· 一个线程读,另一个线程写时也存在线程安全问题

读写锁就是把读操作和写操作区分开来,Java标准库提供了ReentrantReadWriteLock类,实现了读写锁.

        ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
        ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();
        ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();

写操作

        //写操作
        writeLock.lock();//写锁加锁
        //写操作
        writeLock.unlock();//写锁释放锁

读操作 

        //读操作
        readLock.lock();//读锁加锁
        //读操作
        readLock.unlock();//读锁释放锁

注意 

· 读加锁和读加锁之间不互斥

· 写加锁和写加锁之间互持

· 读加锁与写加锁之间互斥

· 只要涉及到“互斥”,就会产生线程的挂起等待,一旦线程挂起,再次被唤醒就不知道要隔多长时间了。

· 减少产生“互斥”的机会,就是提高效率的重要途径

读写锁特别适合一些“频繁读,不频繁写”的场景中 

就比如我们在学校教务系统中查看课表的操作,课表只导入一次,而我们会不断地在教务系统进行查看课表,我们查询课表相当于读操作,课表的导入相当于写操作,此时就适合应用读写锁.

重量级锁与轻量级锁

· 重量级锁:加锁机制重度依赖了OS提供的mutex

· 大量的内核态用户态切换

· 很容易引发线程的调度

 

· 轻量级锁:轻量级锁的加锁机制尽可能不使用mutex,而是尽量在用户态代码完成,实在不行了,再使用mutex

· 少量的内核态用户态切换

· 不容易引发线程的调度

什么是用户态与内核态?

就比如去银行办理业务.

· 在窗口外自己办理业务,这就是用户态,用户态的时间成本是可控的

· 在窗口内工作人员办理业务,这是内核态,内核态的时间成本是不可控的

· 如果办业务的时候需要反复和工作人员沟通,此时就需要不断地重新排队,这样的效率是很低下的.

例如synchronized开始时是一个轻量级锁,如果锁的冲突比较严重,就会变成重量级锁

在后续的synchronized原理中会详细论述synchronized从轻量级锁到重量级锁的转换 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Li_yizYa

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

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

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

打赏作者

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

抵扣说明:

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

余额充值