一、引言
在学习JUC并发包的时,会介绍Lock锁。为了更深入的了解Lock锁的机制,我们可以自定义一个Lock锁,这样去读Lock源码可能好理解一点。
二、自定义Lock锁 1、定义Lock接口public interface Lock { class TimeOutException extends Exception { public TimeOutException(String message) { super(message); } } void lock() throws InterruptedException; void lock(long mills) throws InterruptedException, TimeOutException; void unlock(); Collection<Thread> getBlockedThread(); int getBlockedSize(); }2、Lock实现类
public class BooleanLock implements Lock { // 表示对象的锁是否被占用,true表示对象锁已经被占用 private boolean initValue; // 表示被阻塞线程的集合 private Collection<Thread> blockedThreadCollection = new ArrayList<>(); // 记录获得当前对象锁的线程 private Thread currentThread; public BooleanLock() { this.initValue = false; } /** * 加锁,使用synchronized实现同步 */ @Override public synchronized void lock() throws InterruptedException { // 如果锁已经被占用,则阻塞当前线程 while (initValue) { //将线程加入到阻塞线程集合 blockedThreadCollection.add(Thread.currentThread()); this.wait(); } // 锁没有被占用,则当前线程获得锁 blockedThreadCollection.remove(Thread.currentThread()); this.initValue = true; this.currentThread = Thread.currentThread(); } /** * 当线程等待一定时间后,没有释放锁,则其他线程抛出超时异常 */ @Override public synchronized void lock(long mills) throws InterruptedException, TimeOutException { if (mills <= 0) lock(); long hasRemaining = mills; long endTime = System.currentTimeMillis() + mills; while (initValue) { if (hasRemaining <= 0) throw new TimeOutException("Time out"); blockedThreadCollection.add(Thread.currentThread()); this.wait(mills); hasRemaining = endTime - System.currentTimeMillis(); } this.initValue = true; this.currentThread = Thread.currentThread(); } /** * 释放锁 */ @Override public synchronized void unlock() { // 只有占用锁对象的线程,才能释放锁。不然main线程释放锁,程序会有问题。 if (Thread.currentThread() == currentThread) { this.initValue = false; System.out.println(Thread.currentThread().getName() + " release the lock monitor."); this.notifyAll(); } } @Override public Collection<Thread> getBlockedThread() { //保证更新集合操作安全,不存在安全问题 return Collections.unmodifiableCollection(blockedThreadCollection); } @Override public int getBlockedSize() { return blockedThreadCollection.size(); } }3、测试
public class LockTest { public static void main(String[] args) throws InterruptedException { final BooleanLock booleanLock = new BooleanLock(); //创建4个线程 for (int i = 1; i < 5; i++) { new Thread("T" + i) { @Override public void run() { try { booleanLock.lock(10000); System.out.println(Thread.currentThread().getName() + " have the lock Monitor"); work(); } catch (InterruptedException e) { e.printStackTrace(); } catch (Lock.TimeOutException e) { System.out.println(Thread.currentThread().getName() + " time out"); } finally { booleanLock.unlock(); } }; }.start(); } } private static void work() throws InterruptedException { System.out.println(Thread.currentThread().getName() + " is Working..."); Thread.sleep(40_000); } }4、测试结果
自定义一个Lock锁,熟悉Synchronized的同时,深入理解JUC中的Lock。