并发编程 | synchronized 和 ReentrantLock

作为jvm最常用的锁,synchronized 和ReentrantLock经常会被拿来比较…
(下文一律把synchronized 简写成sync,望周知)

相同点:都是可重入锁(可重入锁也叫递归锁,用于避免获取递归方法的锁时形成死锁。sync是隐式的可重入锁)

不同点:sync使用简单,不用手动lock,unlock;ReentrantLock需要手动加锁释放锁,但是灵活性会更好一些(因为可以设置公平非公平锁,可以设置允许中断等等)。一般情况下直接用sync锁即可,复杂的情况再用reentrantLock。性能方面:sync更笨重(但是jdk某个版本之后引入了锁升级概念,对sync进行了优化,性能OK了很多)

参考文章

有赞coder-Java锁的那些事儿
尚硅谷的这个juc专题的视频还是挺香的

ReentrantLock

1. 可以设置公平锁模式和非公平锁模式

  • 公平锁可以使多个线程持有锁的概率趋于公平。举个例子,假设a,b,c三个线程同时在争夺同一把锁,那么该锁被获取的情况会接近于 a,b,c,a,b,c,a,b,c,雨露均沾。默认模式是非公平锁(unfair),非公平锁有个好处是能最大化地利用CPU的时间片,避免上下文切换造成的损耗

2. ReentrantLock底层原理

reentrantLock介绍与底层原理

在这里插入图片描述

这个问题又可以叫做如何实现ReentrantLock…
提到ReentrantLock,必须要先了解AQS同步器…

我的理解是:实现ReentrantLock,

  • 要有个同步队列用来实现“公平”,就是线程排队(reentrantLock是通过AQS实现的)…这里有点串行化的思想
  • 要实现阻塞(reentrantLock实现时用的是LockSupport的park方法)
  • 要实现唤醒(reentrantLock实现时用的是LockSupport的unpark方法)

(公平锁)大概的过程是:
多个线程abcd一起竞争锁(通过CAS的方式竞争锁),假设a抢到了,就执行任务。
剩下的bcd会被加入同步队列,被加入队列的线程会被阻塞(park)。
直到上一个抢到锁的线程(a)释放锁之后,队列才会又移除一个线程(b),并唤醒它去执行任务。
ps: 这个队列是双向链表,FIFO的类型
其实吧,线程结点插入链表时也会并发的,源码在这有控制(对于没有立即加入的nodes,他们会一直自旋直到加入队列)

3. AQS

略,还没细看。这玩意是并发的基础知识

4. CAS

处理并发的一种方式,属于乐观锁

5. ReentrantLock使用注意事项

记得手动unlock,不然会造成其他线程一直阻塞试图获取锁,最终导致死锁

synchronized

1. 可以修饰方法和代码块,修饰代码块时,会对括号里的对象加锁

2. static sync 和 sync分别对应类锁和对象锁的概念

凡是需要竞争同一把类锁的方法都是竞态的;
凡是需要竞争同一个对象锁的方法都是竞态的;
类锁和对象锁不是竞态的(比如People类锁,和People的一个对象p生成的对象锁不是互斥的)

3. jdk对sync做了哪些优化

略,大概是锁升级。讲这个又要扯到对象头巴拉巴拉

4. sync底层原理

和monitor有关,但我不是很清楚。。

5.为啥wait等关键字要搭配sync一起使用

还和monitor有关,但我不是很清楚。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值