模仿ReentrantLock类自定义锁
简介
临近过年了,没什么需求,今天模仿ReentrantLock自定义写了一个自己锁,在这里记录一下,前提是对AQS原理有所了解,分享给大家
1、自定义锁MyLock
package com.jacky; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.AbstractQueuedSynchronizer; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; /** * Created by jacky on 2018/2/12. */ public class MyLock implements Lock{ private final Sync sync; /** * 创建公平锁或非公平锁 * @param fairFlag */ public MyLock(boolean fairFlag){ sync = fairFlag ? new FairSync() : new NonFairSync(); } /** * 默认是公平锁 */ public MyLock(){ sync = new FairSync(); } /** * 获取锁 */ @Override public void lock() { sync.acquire(1); } /** * 获取可中断锁 * @throws InterruptedException */ @Override public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } /** * 它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false, * 也就说这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待 * @return */ @Override public boolean tryLock() { return sync.nonfairTryAcquire(1); } /** * 获得可超时的锁 * @param time * @param unit * @return * @throws InterruptedException */ @Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1,unit.toNanos(time)); } /** * 释放锁 */ @Override public void unlock() { sync.release(1); } @Override public Condition newCondition() { return sync.new ConditionObject(); } abstract static class Sync extends AbstractQueuedSynchronizer { /** * 判断当前线程是否获得锁 * @return */ @Override protected boolean isHeldExclusively() { return Thread.currentThread() ==getExclusiveOwnerThread(); } /** * 尝试释放锁 * @param arg * @return */ @Override protected boolean tryRelease(int arg) { int newState =getState()-arg; setState(newState < 0 ? 0:newState); if (newState ==0){ setExclusiveOwnerThread(null); } return true; } final boolean nonfairTryAcquire(int arg) { Thread thread = Thread.currentThread(); int state = getState(); if (state ==0){ compareAndSetState(0,state+arg); //设置独占线程 setExclusiveOwnerThread(thread); return true; } if (isHeldExclusively()){ setState(state+arg); return true; } return false; } } static class FairSync extends Sync{ /** * 尝试公平锁获得锁 * @param arg * @return */ @Override public boolean tryAcquire(int arg) { Thread thread = Thread.currentThread(); int state = getState(); if (state ==0){ //判断队列是否有数据,有数据就返回获取锁失败(公平锁才会这么做) if (hasQueuedPredecessors()){ return false; } compareAndSetState(0,state+arg); //设置独占线程 setExclusiveOwnerThread(thread); return true; } if (isHeldExclusively()){ setState(state+arg); return true; } return false; } } static class NonFairSync extends Sync{ @Override public boolean tryAcquire(int arg) { return nonfairTryAcquire(arg); } } }
2、测试类
package com.jacky; import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode; import java.util.concurrent.CountDownLatch; import java.util.concurrent.locks.ReentrantLock; /** * Created by jacky on 2018/2/12. */ public class MyLockDemo { private final static MyLock lock = new MyLock(false); //private final static ReentrantLock lock = new ReentrantLock(true); private static int num = 0; public static void main(String[] args) { int count = 2000; CountDownLatch countDownLatch = new CountDownLatch(count); Runnable runnable = new Runnable() { @Override public void run() { try { lock.lock(); Thread thread = Thread.currentThread(); System.out.println("--start--"+thread.getName()); try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } num++; System.out.println("--end--"); countDownLatch.countDown(); }finally { lock.unlock(); } } }; Thread thread = null; for (int i = 0; i < count; i++) { thread = new Thread(runnable,"t"+i); thread.start(); } try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("--num--"+num); } }