赞
踩
ReentrantLock也称为重入锁,顾名思义,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁。除此之外,该锁的还支持获取锁时的公平和非公平性选择。
重进入是指任意线程在获取到锁之后能够再次获取该锁而不会被锁所阻塞,该特性实现需要解决两个问题。
public class MartionReentrantLock implements Lock { //标记重入次数的count值 AtomicInteger count = new AtomicInteger(0); //锁的拥有者 AtomicReference<Thread> owner = new AtomicReference<>(); //等待队列 private LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue<>(); @Override public boolean tryLock() { //判断count是否为0,若count!=0,说明锁被占用 int ct = count.get(); if (ct !=0 ){ //判断锁是否被当前线程占用,若被当前线程占用,做重入操作,count+=1 if (owner.get() == Thread.currentThread()){ count.set(ct + 1); return true; }else{ //若不是当前线程占用,互斥,抢锁失败,return false return false; } }else{ //若count=0, 说明锁未被占用,通过CAS(0,1) 来抢锁 if (count.compareAndSet(ct, ct +1)){ //若抢锁成功,设置owner为当前线程的引用 owner.set(Thread.currentThread()); return true; }else{ //CAS操作失败,说明情锁失败 返回false return false; } } } @Override public void lock() { //尝试抢锁 if (!tryLock()){ //如果失败,进入等待队列 waiters.offer(Thread.currentThread()); //自旋 for (;;){ //判断是否是队列头部,如果是 Thread head = waiters.peek(); if (head == Thread.currentThread()){ //再次尝试抢锁 if (!tryLock()){ //若抢锁失败,挂起线程,继续等待 LockSupport.park(); }else{ //若成功,就出队列 waiters.poll(); return; } }else{ //如果不是,就挂起线程 LockSupport.park(); } } } } @Override public void unlock() { if (tryUnlock()){ Thread th = waiters.peek(); if (th !=null){ LockSupport.unpark(th); } } } public boolean tryUnlock(){ //判断,是否是当前线程占有锁,若不是,抛异常 if (owner.get() != Thread.currentThread()){ throw new IllegalMonitorStateException(); }else{ //如果是,就将count-1 若count变为0 ,则解锁成功 int ct = count.get(); int nextc = ct-1; count.set(nextc); //判断count值是否为0 if (nextc == 0){ owner.compareAndSet(Thread.currentThread(), null); return true; }else{ return false; } } } @Override public void lockInterruptibly() throws InterruptedException { } @Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { return false; } @Override public Condition newCondition() { return null; } }
public void MartionData() { readLock.lock(); if (!update) { // 必须先释放读锁 readLock.unlock(); // 锁降级从写锁获取到开始 writeLock.lock(); try { if (!update) { // 准备数据的流程(略) update = true; } readLock.lock(); } finally { writeLock.unlock(); } // 锁降级完成,写锁降级为读锁 } try { // 使用数据的流程(略) } finally { readLock.unlock(); } }
/** * Martion * implements ReentrantReadWriteLock (1.1 edition) */ public class MartionReadWriteLock { private AtomicInteger rCount = new AtomicInteger(0); private AtomicInteger wCount = new AtomicInteger(0); private AtomicReference<Thread> owner = new AtomicReference<>(); private LinkedBlockingQueue<Node> waiters = new LinkedBlockingQueue<>(); class Node { int type ;//0:获取写锁的标志 1:获取读锁(共享锁)的标志 Thread thread;//当前线程 int arg;//修改线程的内部次数 public Node(Thread thread,int type,int arg){ this.thread = thread; this.type = type;// 0 写入 1 读取 this.arg = arg; } } /** * * @param accquire * @return true 获取锁成功 false 获取锁失败 */ //写锁实现 public boolean tryAccquired(int accquire){ if (rCount.get()!=0) return false; int wsCount = wCount.get(); if (wsCount==0){ if (wCount.compareAndSet(wsCount,wsCount+accquire)) owner.set(Thread.currentThread()); return true; }else if (owner.get() == Thread.currentThread()){ wCount.compareAndSet(wsCount,wsCount+accquire); return true; } return false; } /** * 获取写锁 */ public void lock(){ int arg = 1; if (!tryAccquired(arg)){ Node node = new Node(Thread.currentThread(), 0, arg); waiters.offer(node); for (;;){ Node head = waiters.peek(); if (head!=null&&head.thread == Thread.currentThread()){ if (!tryAccquired(arg)){ LockSupport.park(); }else{ waiters.poll(); return; } }else { LockSupport.park(); } } } } /** * 尝试释放写锁 * @param release true 尝试释放锁成功 false 尝试释放锁失败 * @return */ public boolean tryUnlock(int release){ if (owner.get()!=Thread.currentThread()) return false; int count = rCount.get(); int cureent = count - release; rCount.set(cureent);//无论是否完全释放 都先设置count值 if (cureent == 0){ owner.compareAndSet(Thread.currentThread(),null); return true; } return false; } /** * 释放写锁 * @return true 释放锁成功 false 释放锁失败 */ public boolean unLock(){ int arg = 1 ; if (tryUnlock(arg)){ Node peek = waiters.peek(); if (peek!=null){ Thread thread = peek.thread; LockSupport.unpark(thread); } return true; } return false; } /** * 尝试释放读锁 1:获取读锁成功 -1:获取读锁失败 */ //读锁实现(共享锁) public int tryLockShard(int accqure){ for (;;){ if (wCount.get()!=0&&owner.get()!=Thread.currentThread()){ return -1; } if (rCount.compareAndSet(rCount.get(),rCount.get()+accqure)){ return 1; } } } /** * 释放读锁 */ public void lockShard(){ int arg = 1; if (tryLockShard(arg)<0){ Node node = new Node(Thread.currentThread(), 1, arg); waiters.offer(node); for (;;){ Node heads = waiters.peek(); if (heads!=null&&owner.get()==Thread.currentThread()){ if (tryLockShard(arg)>=0){ Node poll = waiters.poll(); //判断下一级列表是否还为读操作 Node next = waiters.peek(); if (next!=null&&next.type == 1){ LockSupport.unpark(next.thread); } return; }else { LockSupport.park(); } }else { LockSupport.park(); } } } } /** * 尝试释放读锁 * @param release * @return true 尝试释放锁成功 false 尝试释放锁失败 */ public boolean tryUnLockShard(int release){ for (;;){ int rc = rCount.get(); int current = rc-release; if (rCount.compareAndSet(rc,current)) return current==0; } } /** *释放读锁 * @return true 释放锁成功 false 释放锁失败 */ public boolean unLockShard(){ int arg = 1; if (tryUnLockShard(arg)){ Node peek = waiters.peek(); if (peek!=null){ LockSupport.unpark(peek.thread); } return true; } return false; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。