学校网站建设审批,中国建筑网官网平台,wordpress 首页展示,十大免费行情软件入口下载锁 锁是用来锁东西的#xff0c;让别人打不开也看不到#xff01;在线程中#xff0c;用这个“锁”隐喻来说明一个线程在“操作”一个目标#xff08;如一个变量#xff09;的时候#xff0c;如果变量是被锁住的#xff0c;那么其他线程就对这个目标既“操作”不了…锁 锁是用来锁东西的让别人打不开也看不到在线程中用这个“锁”隐喻来说明一个线程在“操作”一个目标如一个变量的时候如果变量是被锁住的那么其他线程就对这个目标既“操作”不了挂起也无法看到目标的内容对Java并发包锁的实现基本在java.util.concurrent.locks包中说“基本”是因为在java.util.concurrent中还有CountDownLatch(可以看成带计数器的锁)CyclicBarrierSemaphore类似于信号量但是也可以看成一个特殊的锁。这里我们先以java.util.concurrent.locks包为主来讨论锁的问题吧。我们来看看java.util.concurrent.locks包中到底有多少“锁”主要是这样几个接口及其实现 Lock---------- |---------ReadLock //读锁 |------ReentrantLock //并发锁 |------WriteLock //写锁 ReadWriteLock---------------- |-------------ReentrantReadWriteLock //并发读写锁 以上Lock和ReadWriteLock都是接口是锁行为的契约其余部分都是实现而ReadLock和WriteLock是作为ReentrantReadWriteLock的静态内部类存在不能直接使用也就是他们是ReentrantReadWriteLock的支持类不是向外提供给外部程序使用的 另外还发现有这样抽象类 AbstractOwnableSynchronizer--------- |----------AbstractQueuedLongSynchronizer |-------AbstractQueuedSynchronizer 这几个都是抽象类但是没有明显的实现没有实现其实是所有的Lock在其实现时使用的基础结构并且以来它们实现了锁的机制只要我们先把这几个抽象类的实现逻辑搞清楚Lock的原理就比较清楚了理解了原理使用Lock时就有的放矢了。 另外包中还有condition接口 Condition------------ |--------- ConditionObject 这个接口和实现是干什么的是用来实现“竞赛条件”的提供更加细粒度的线程锁控制也就是在某个条件下加锁等操作。 好了java.util.concurrent.locks 中的基本“布局”和“结构”现在已经比较清楚了下面我们将从AbstractOwnableSynchronizer抽象类开始讲这是整个Lock的核心明白其实现能让你了解如何“准确”的使用锁而不是仅仅“知道电视机的按钮而不知道里面的原理”毕竟我们是搞开发的对原理更应该重视你说是吧 AbstractOwnableSynchronizer 它依靠于CLH队列来实现锁的机制 * ------ prev ----- ----- * head | | ---- | | ---- | | tail * ------ ----- ----- 采用的CHL模型采用下面的算法完成FIFO的入队列和出队列过程,而正是入队和出队的实现“模拟”了“锁”的效用 对于入队列(enqueue)采用CAS操作每次比较尾结点是否一致然后插入的到尾结点中。 do { pred tail; }while ( !compareAndSet(pred,tail,node) ); 对于出队列(dequeue):由于每一个节点也缓存了一个状态决定是否出队列因此当不满足条件时就需要自旋等待一旦满足条件就将头结点设置为下一个节点。 while (pred.status ! RELEASED) ; head node; 有三个核心字段 private volatile int state; private transient volatile Node head; private transient volatile Node tail; 其中state描述的有多少个线程取得了锁对于互斥锁来说state1。head/tail加上CAS()操作就构成了一个CHL的FIFO队列。下面是Node节点的属性。 volatile int waitStatus; 节点的等待状态一个节点可能位于以下几种状态 CANCELLED 1 节点操作因为超时或者对应的线程被interrupt。节点不应该不留在此状态一旦达到此状态将从CHL队列中踢出。 SIGNAL -1 节点的继任节点是或者将要成为BLOCKED状态例如通过LockSupport.park()操作因此一个节点一旦被释放解锁或者取消就需要唤醒LockSupport.unpack()它的继任节点。 CONDITION -2表明节点对应的线程因为不满足一个条件Condition而被阻塞。 0 正常状态新生的非CONDITION节点都是此状态。 非负值标识节点不需要被通知唤醒。 volatile Node prev;此节点的前一个节点。节点的waitStatus依赖于前一个节点的状态。 volatile Node next;此节点的后一个节点。后一个节点是否被唤醒uppark()依赖于当前节点是否被释放。 volatile Thread thread;节点绑定的线程。 Node nextWaiter;下一个等待条件Condition的节点由于Condition是独占模式因此这里有一个简单的队列来描述Condition上的线程节点。 以上只是一个简单的描述吧只要知道AbstractOwnableSynchronizer的核心是一个CHL队列而AbstractOwnableSynchronizer是所有Lock的基础在讲具体Lock的时候我将“回溯”到AbstractOwnableSynchronizer凡是具体Lock调用AbstractOwnableSynchronizer的方法的时候我将具体讲一下其实现并对应着Lock对应方法的实现这样就能彻底搞清楚具体Lock的原理了也就能在使用时游刃有余了。 对于那些真正需要探知Lock一切底细的家伙而言我找了个文档作为附件是并发作者的论文不过你需要英文好一些才可以哦转载于:https://www.cnblogs.com/isoftware/p/3794996.html