版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、发包的作者是大名鼎鼎的Doug Lea。在接下来的课程中,回去剖析一些经典Lock在J.U.C中是最的组件,前面讲synchronized的时候,锁最重过 J.U.C 包中的所有组件,一定会发现绝大部分的组件都有用到了 Lock。所以通过Lock 作为切入点使得在后续的学习过程中会更加轻松。Lock在 Lock 接口出现之前,Java 中的应用程序对于多线程的并发安全处理只能基于 synchronizedsynchronized也就是它并不适合于所有的并发场景。但是在 Java5 以后,Lock 的出现可以解决 synchronized 在某些场景中的短板,它比synchronized 更加灵
2、活。ReentrantReadWriock:重入读写锁,它实现了 ReadWri ock 接口,在这个类中了两个锁,一个是ReadLock,一个是Wriock,他们都分别实现了Lock是: 读和读不互斥、读和写互斥、写和写互斥。也就是说涉及到影响数据变化的: stampedLock 是一种乐观的读策略,使得乐观锁完全不会阻塞写线程Lock 的类关系锁锁voidunlock()timeout, TimeUnit void lock() / void lockInterruptibly() / 和 lock()方法相似, 但阻塞的线on 异常boolean tryLock() / 非阻塞返回Ree
3、ntrantLock 重入锁,表示支持重新进入的锁,也就是说,如果当前线程t1 通过调用lock重入锁,表示支持重新进入的锁,也就是说,如果当前线程t1 通过调用lock 重入锁的设计比如调用demo 方法获得了当前的对象锁,然后在这个方法中再去调用 publicclasspublic synchronized void demo() public void demo2() synchronized (this)publicstatic void main(String args) ReentrantDemord=newReentrantDemo(); new Thread(rd:demo).
4、start();ReentrantLock 的使用案publicclassAtomicDemoprivatestaticintstaticLockpublicclassAtomicDemoprivatestaticintstaticLocklock=newpublicstaticvoidtrycatch(InterruptedExceptione)publicstaticvoidmain(Stringargs)for(intnewThread()-线程和其他写线程都会被阻塞。读写锁了一对锁,一个读锁、一个写锁;一般publicclassLockDemostaticMapcacheMap=pub
5、licclassLockDemostaticMapcacheMap=newstaticockstaticLockstaticLockpublicstaticfinalObjectget(Stringkey)数据System.out.println(开始read.lock(); /读tryreturnfinallypublicstaticfinalObjectput(StringpublicstaticfinalObjectput(Stringkey,ObjectSystem.out.println(开始写数据returnfinallyReentrantLock 的实现行执行,从而达到线程安全性
6、的目的。在 synchronized 中,分析了偏向锁、轻量级锁、乐观锁。基于乐观锁以及自旋锁来优化了 synchronized 的加锁开销,AQS在 Lock 中,用到了一个同步队列 AQS,全称么 J.U.C 中绝大部分的工具都能轻松掌握。AQS 的两种共享锁,允许多个线程同时获取锁,并发 共享资源,比AQS 的实AQS队的是一个FIFO的双向链表,这种结构的特点是每个数据结一个节点开始很方便的前驱和后继。每个 Node 其实是由线程封装,当线程 争抢锁失败后会封装成Node加入到ASQ队列中去;当获取锁的线程锁以后,Node 的组锁以及添加线程对于队列的新的线程封装成Nodeprev点的
7、前置节点的 next 节点指向自己通过CAS 讲tail新的获得锁的节点,将prev 的指针指向设置 head 节点不需要用 CAS,原因是设置 head 节点是由获得锁的线程来完成CAShead设置为原首节点的后继节点,并且断开原head节点的next即的源码ReentrantLock 调用ReentrantLocklock这个是reentrantLockpublicpublicvoidlock() 业务功能,所以在不同的同步场景中,会继承AQS 来实现对应场景的功能 Sync 有两个具体的实现类,分别是:表示所有线程严格按照FIFO以非公平锁为例,来看看lock没有线程排队,我先上来 ca
8、s 去抢占一下CASacquire(1finalvoidlock()if(compareAndSetState(0,CAS 的实stateOffsetstateOffset,expect,protectedfinalbooleancompareAndSetState(int expect, int update) /Seebelowforintrinsicssetupto通过 cas 乐观锁的方式来做比较并替换,这段代码的意思是,如果当前内存中的 stateexpectupdatetrue,否则返回false.以及涉及到 state 这个属性的意义。state 是 AQS 中的一个属性,它在不
9、同的实现中所表达的含义不一样,对于重入当 state0 时,表示已经有线程获得了锁,也就是 state=1 , 但是因为 Unsafe 类是在sun.misc 包下,不属于Java 标准。但是很多Java 的基础类库,包括一些被广泛使用的高性能开发库都是基于 Unsafe 类开发的,比如 Netty、 Hadoop、Kafka 等;Unsafe可认为是Java中留下的后门,提供了一些低层次操作,如直接内存、而 CAS 就是 Unsafe 类中提供的一个原子操作,第一个参数为需要改变的对象,第二个为偏移量(即之前求出来的 headOffset 的值),第三个参数为期待的值,第四个为更新后的值整个
10、方法的作用是如果当前时刻的值等于预期值var4 相等,则更新为新的期望值 var5,如果更新成功,则返回true,否则返回 false;一个JavastateOffsetstateAQSpareAndSwapInt(JNIEnv*env, unsafe, jobject obj, jlong offset, jint e, jint x) unsafe, jobject obj, jlong offset, jint e, jint x) oop p = JNIHandles:resolve(obj);/将JavaJVMoop(普通returnjint)(Atomic:cmpxchg(xadd
11、reecasx示需要更新的值,addr 表示 state 在内存中的地址,e 表示预期值 acquireAQSCASstate0,此时继续acquire(1)操作通过tryAcquiretrue如果tryAcquire 失败,则会通过addWaiter 方法将当前线程封装成Node到 AQS 队列尾部publicpublicfinalvoidacquire(intarg)if (!tryAcquire(arg) & acquireQueued(addWaiter(Node.EXCLUSIVE),arg)这个方法的作用是尝试获取锁,如果成功返回true它是重写 AQS 类中的tryAcquire
12、方法,并且大家仔细看一下AQS中tryAcquireprotectedprotectedfinalbooleantryAcquire(intacquires)returnfinalfinalbooleannonfairTryAcquire(intacquires)finalThreadcurrentThread.currentThread();/获取当前执intcgetState();/stateif(c0if(compareAndSetState(0acquires)cas替换state的值,cas 成功表示获取锁成功sEliOehacrt,returnelseif(currentgetEx
13、clusiveOwnerThread如果同一intnextc=c+if(nextc0)/thrownewError( return true;returnumlockcount当 tryAcquire 方法获取锁失败以后,则会先调用 addWaitermodeNode.EXCLUSIVE,表示独占状态。意味着重入锁用到了 AQS 的独占锁功能将当前线程封装成tailcascasenqAQSprivateNodeaddWaiter(Nodemode)NodenodenewNode(Thread.currentThreadmode);/把当前线程封装为 NodeNodepredtailtail是A
14、QS中表示同比队列队尾的属性,默认是nullif(prednulltail不为空的情况下,说明队列中存在节node.prev =pred;/把当前线程的Nodeprevif(compareAndSetTail(prednodecas加入AQS队列,也就是设置为 指向当前returnenq(node);/tail=null,把node添加到同步队returnprivateprivateNodeenq(finalNodenode)for(;)Nodet=if(t=null)/Mustif(compareAndSetHead(newtail=elsenode.prev=if(compareAndSe
15、tTail(t,node) t.next = node;return通过 addWaiter 方法把线程添加到链表后,会接着把 Node 作为参数传递给获取当前节点的prev 节点如果prev 节点为headtryAcquireheadThreadA了锁ThreadA了锁,然后设置head为 ThreadB获得执行finalbooleanacquireQueued(finalNodenode,arg)booleanfailed=true; try booleaninterrupted=false; for (;) finalNodepnode.predecessor();/取当前节点的prev
16、 节if(phead&tryAcquire(arg/如果是head节点,说明有资格去争抢锁etHead(node); /获取锁成功,也限p.nextnull/把原head节点从链表移failed = false; returninterrupted;/ThreadA可能还没锁,使得ThreadB在执行 tryAcquire 时会返回falseifnode)interruptedinterruptedtrue并且返回当前线程finallyif通过 cas 进行竞争锁操作。成功表示获得锁,失败表示获得锁失败失败,那么失败以后会调用shouldParkAfterFailedAcquire 方法CAN
17、CELLED(1,SIGNAL(-1CANCELLED: 在同步队列中等待的线程等待超时或被中断,需要从同步队列中取消该Node 的结点, 其结点的waitStatus 为CANCELLED,即结束状态,进入该状SIGNAL:只要前置节点锁,就会通知标识为SIGNAL状态的后续节点的线CONDITION: 和Condition 有关系,后续会讲解 NodeThreadAThreadA 的predSIGNAL通过循环扫描链表把CANCELLED修改pred 节点的状态为SIGNAL,返回returnreturn true;/返回 true起if(ws0/ws0prev节点取消了排donode.p
18、rev=pred=,private static boolean shouldParkAfterFailedAcquire(Nodepred,Node node) intwspred.waitStatus;/相当于pred=pred.prev; while(pred.waitStatus0/这里采用循环,从双向列表中移除CANCELLED 的节点pred.next=else/利用 cas设置prev节点的状态为 compareAndSetWaitStatus(pred,ws, return使用LockSupport.park 挂起当前线程编程WATING 状态 Terrupted,返回当前线程
19、是否被其他线程触发过中断请求,也就是 errupt(); 如果有触发过中断请求,那么这个方返回当前的中断标识 着在acquire 方法中会执行 selfInterrupt()。privatefinalbooleanparkAndCheckInterrupt()returnselfInterrupt: 标识如果当前线程在 acquireQueued 中被中断过,则需要产生一acquireQueuedstaticstaticvoidselfInterrupt()图解意味着ThreadB 和 ThreadC 只能挂起了。实际上是调用了Unsafe 类里的函数,归结到Unsafe 里,只有两个函数点像
20、信号量,但是这个“”是不能叠加的,“”是的。park 会消费permit0。 如果再调用一次parkpermit0 了。直到permit1unparkpermit1.每个线程都有一个相关的permit,permit 最多只有一个,重复调用 unpark 不会累积锁的流 在unlock 中,会调用release方法来NodeNodehheadaqsheadif(hnull&h.waitStatus0)/head节点不为空并且状态!=0.调用 unparkSuccessor(h)唤醒后续节点returnreturnif(tryRelease(arg)publicfinalbooleanreleas
21、e(intarg)在排它锁中,加锁的时候状态会增加 1(当然可以自己修改这个值,在的时的次数与 lock(Owner 线程设置为空,而且也只有这种情况下才会返回tectedprotectedfinalbooleantryRelease(intintc=getState()-if(Thread.currentThread()!= thrownewbooleanfree=false; if (c = 0) free = true; returnprivatevoidunparkSuccessor(Nodenode)intwsnode.waitStatus;/获得head节点的if(ws0)/如果下
22、一个节点为 null或者status0表示 cancelled状态/通过从尾部节点开始扫描,找到距离 head最近的一waitStatus=0 的节s= for(Nodet=tail;t!=null&t!=node;t= if(t.waitStatus=0) s = t;if(snullnext节点不为空,直接唤醒这个线程即为什么在锁的时候是从 tail 进行扫这个问题有几个同学问过我,我觉得有必要单独拧出来说一下,再回到 将新的节点的prev 指向 将privateNodeenq(finalNodenode)for(;)Nodet=if(t=null)/Mustif(compareAndSe
23、tHead(newtail=elsenode.prev=if(compareAndSetTail(t,node)t.next=return开始往后遍历,由于 t.next=node 还没执行意味着链表的关系还没有建立完整。就会导致遍历到 t 节点的时候被中断。所以从后往前遍历,一定不会存在这个问图解ThreadB 被唤醒原本挂起的线程继续行大家还有印象吧。 原来被挂起的线程是在 acquireQueued 方法中,所以被唤这个方法前面已经完整分析过了,只关注一下ThreadB被唤醒以后的执行流由于ThreadB的prev节点指向的是head,并且ThreadA已经了锁。所以这个时候调用tryAcquire 方法时,可以顺利获取到锁finalbooleanacquireQueued(finalNodenode,arg)b
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 利用基因编辑技术改进微生物脂质积累
- 三明市2024-2025学年第一学期高一期末数学质检主观题阅卷情况和教学建议
- 2024高中生物第二章动物与人体生命活动的调节第2节通过激素的调节精练含解析新人教版必修3
- 2024高中语文第二单元置身诗境缘景明情自主赏析登岳阳楼学案新人教版选修中国古代诗歌散文欣赏
- 2024高考地理一轮复习第八章第1讲农业的区位选择教案含解析新人教版
- 2024高考历史一轮复习方案专题十一世界经济的全球化趋势专题综合测验含解析人民版
- 2024高考地理一轮复习第一部分自然地理-重在理解第二章地球上的大气规范答题2气候类综合题学案新人教版
- DB42-T 2334-2024 水土保持区域评估技术导则
- 2024年湖北国土资源职业学院高职单招职业技能测验历年参考题库(频考版)含答案解析
- 二零二五年度新能源技术共享与推广实施合同3篇
- 2025年正定县国资产控股运营集团限公司面向社会公开招聘工作人员高频重点提升(共500题)附带答案详解
- 刘宝红采购与供应链管理
- 2025共团永康市委下属青少年综合服务中心驻团市委机关人员招聘2人(浙江)高频重点提升(共500题)附带答案详解
- 2025年计算机二级WPS考试题目
- 部编人教版语文小学六年级下册第四单元主讲教材解读(集体备课)
- EPC项目投标人承包人工程经济的合理性分析、评价
- 社区电动车棚新(扩)建及修建充电车棚施工方案(纯方案-)
- 籍贯对照表完整版
- 供应商年度审核计划及现场审核表
- 环甲膜穿刺ppt课件
- 隐蔽工程验收记录(大全)
评论
0/150
提交评论