J.U.C包之Lock接口及其实现

锁的本质
锁是对资源的一种保护和约束,抢锁是获得使用资源的资格。
锁的实现原理:
维护一个状态值,通过CAS操作这个状体值,操作成功得到锁,操作失败进行自旋。如轻量级锁自旋,线程是Runable状态;重量级锁自旋,线程进入entryList,是blocked状态。

Lock接口
lock():获取锁(不死不休)
tryLock():获取锁(浅尝则止)
tryLock(long time, TimeUnit unit):获取锁(过时不候)
lockInterruptibly():获取锁(任人摆布),会一直等候加锁而阻塞,但可由其他线程打断

unlock():释放锁
Condition new Condition():类似于一个锁池,与sync里面的waitset相似
理解:Object中的wait()、notify()只能和sync配合使用,可以唤醒一个或者全部(单个等待集);Condition需要与Lock配合使用(如lock.newCondition(),可以new多个,每个对应一个等待池),但可以提供多个等待集合,更精确的控制。

结论:

  1. lock()最常用,一般采用reentrantLock实现,加锁和解锁的次数一定要相同。可多次加锁(可重入),少解锁会导致其他线程拿不到锁,多解锁会报错。
  2. lockInterruptibly()方法一般更昂贵,有的impl可能没有实现它。

阻塞队列
一个可以放n个元素的队列,队列满时,再往里面put会阻塞;队列空时,从里面take会阻塞。

ReentrantLock原理
在这里插入图片描述
synchronized vs lock
synchronized
优点:1.使用简单,语义清晰,哪里需要点哪里
2.由JVM提供,提供了多种优化方案(锁粗化、锁消除、偏向锁、轻量级锁)
3.锁的释放由虚拟机来完成,不用人工干预,也降低了死锁的可能性
缺点:无法实现一些锁的高级功能如:公平锁、中断锁、超时锁、读写锁、共享锁等

lock
优点:1、所有synchronized的缺点 2、可以实现更多的功能
缺点:需手动释放锁unlock,新手使用不当可能造成死锁

hashTable vs hashmap
hashTable:线程安全,其中put和get都加了sync关键字,效率低,一般不用,除非确实需要
hashmap:非线程安全
理解:因为hashTable中读操作、写操作都是加的互斥锁(sync),为提高性能,可以分别加读锁、写锁,即ReadWriteLock。

ReadWriteLock
维护一对关联锁,一个只用于读操作,一个只用于写操作;读锁是可以多个线程持有,写锁是排他的。同一时间,两把锁不能被不同线程持有(互斥)。

适用场景:适合读取操作多于写操作的场景,改进互斥锁的性能,比如集合的并发线程安全性改造、缓存组件。
锁降级:指的是写锁降级为读锁。持有写锁的同时,再获取读锁,随后释放写锁的过程。写锁是线程独占,读锁是共享,所以写->读是降级。(读->写,不能实现)
注意:锁降级的情况下,允许互斥使用,即先加写锁、加读锁、解写锁。
在这里插入图片描述
其中,owner只和writeCount相关,即owner只记录谁抢到了写锁,若写锁释放了,Owner为空,此时可能readCount不为0(考虑锁降级的情况)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值