Java多线程再学习,温故知新(六)公平锁

公平锁

公平是针对锁的获取而言的,如果一个锁是公平的,那么锁的获取顺序就应该符合请求的绝对时间顺序。可以通过控制队列来实现一个公平锁,线程进入队列后,每次都唤醒队列中的第一个线程。

公平锁的实现

import java.util.ArrayList;
import java.util.List;

public class FairLock {
	private boolean isLocked = false;
	private Thread lockingThread = null;
	private List<QueueObject> waitingThreads = new ArrayList<QueueObject>();
	boolean isLockedForThisThread = true;

	public void lock() throws InterruptedException {
		QueueObject queueObject = new QueueObject();
		synchronized (this) {
			waitingThreads.add(queueObject);
		}
		// 可重入锁实现
		while (isLockedForThisThread) {
			synchronized (this) {
				isLockedForThisThread = isLocked || waitingThreads.get(0) != queueObject;
				if (!isLockedForThisThread) {
					isLocked = true;
					waitingThreads.remove(queueObject);
					lockingThread = Thread.currentThread();
					return;
				}
			}

			try {
				queueObject.doWait();
			} catch (InterruptedException e) {
				synchronized (this) {
					waitingThreads.remove(queueObject);
				}
				throw e;
			}
		}
	}

	public synchronized void unlock() {
		if (this.lockingThread != Thread.currentThread()) {
			throw new IllegalMonitorStateException("Calling thread has not locked this lock");
		}
		isLocked = false;
		lockingThread = null;
		if (waitingThreads.size() > 0) {
			// 将队列的第一个元素叫醒
			waitingThreads.get(0).doNotify();
		}
	}
}

 队列实现类

public class QueueObject {

	private boolean isNotified = false;

	public synchronized void doWait() throws InterruptedException {
		// 只要没被叫醒就一直等待
		while (!isNotified) {
			this.wait();
		}
		this.isNotified = false;
	}

	public synchronized void doNotify() {
		this.isNotified = true;
		// 当前等待的就被叫醒
		this.notify();
	}

	public boolean equals(Object o) {
		return this == o;
	}
}

猜你喜欢

转载自blog.csdn.net/ieflex/article/details/86590553