JAVA基础——Locks系列——总纲

今天面试的时候被问到synchronizer的底层实现,当时脑子里有图但是怎么也说不出来就很绝望,回来一看往年笔记果然还是漏了很多点以及答错的部分。还是对这段的代码理解得不够透彻,写文章梳理一下。

并发容器J.U.C(java.util.concurrent),存放了所有的并发类,包括并发工具、并发集合,锁等等。

JAVA之所以会有多线程问题,就在于JAVA内存模型(JMM)

多线程修改就会触发数据混乱。

解决方法:

1.JMM使用volatile保证部分的可见性,但是volatile的局限性在于只能在一写多读的情况下保证。

2.使用原子操作类(Atomic···)

        这一类就基于CAS机制+自旋

一、AQS

        AbstractQueuedSynchronizer,是并发容器J.U.C(java.util.concurrent)下locks包内的一个抽象类。它实现了一个FIFO(FirstIn、FisrtOut先进先出)的队列以及state(被volatile修饰)变量。底层实现的数据结构是一个双向链表。有两种模式:独占式和共享式

1.

AQS关键工程类截图
AQS关键工程类截图——AbstractOwnableSynchronizer

 2.

AQS关键工程类截图——AbstractQueuedSynchronizer
AQS关键工程类截图——AbstractQueuedSynchronizer

 详细连接:AQS分析(含底层)icon-default.png?t=N7T8http://t.csdn.cn/RUc49

二、CAS

        CAS是compare and swap的缩写,即我们所说的比较交换。cas是一种基于锁的操作,而且是乐观锁。在java中锁分为乐观锁和悲观锁。悲观锁是将资源锁住,等一个之前获得锁的线程释放锁之后,下一个线程才可以访问。而乐观锁采取了一种宽泛的态度,通过设定条件加锁的方式来处理资源,比如通过给记录加version来获取数据,性能较悲观锁有很大的提高。

        只能有一个变量

                解决方案:使用AtomicReferce

        ABA问题:看似没有被改过的值实际上被修改过。比如 i= 1  ->  i=2 -> i=1。

                解决方案:使用 AtomicStampedReference这个类,可以增加时间戳

        CPU开销大

三、synchronizer

四、ReentrantLock

        是基于AQS实现的。在lock()方法中,执行了Sync(抽象类)的lock()方法,而Sync是继承了AQS。且Sync有两个实现子类,一个FairSync(公平锁)一个NonfairSync(非公平锁)。

        1.公平锁

        2.非公平锁

                多了一个属性判断,直接尝试CAS,尝试将state变为1,如果成果就获取资源。如果失败则进行下一步。

第一步:尝试拿锁;第二步:查看addWaiter;第三步:查看acquireQueued

第一步:尝试拿锁(

tryAcquire(int arg);

第二步:查看addWaiter。没拿到锁,需要排队;

addWaiter();

第三步:查看acquireQueued。挂起线程以及被唤醒后续步骤。

五、ReentrantReadWeiteLock

六、CountDownLatch

七、Swmphore

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值