Java并发编程——自定义Lock锁

一、引言

在学习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。

发布了123 篇原创文章 · 获赞 230 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/zxd1435513775/article/details/88430143
今日推荐