何为公平锁:
线程的运行,根据线程的提交(start() 方法的调用时间点),依次执行。
公平锁实现的原理:
1、使用链表来维护数据。(方便获取头节点)
2、当一个线程过来,就创建一个节点,节点中存放的内容为,wait()的对象。
3、当上一个线程结束,则获取头节点,获取节点中存放的对象,调用对象的notify()方法,唤醒正在等待的线程。
4、移除已经唤醒了的节点数据。
重点:每一个线程的wait方法,都使用对应的对象来调用。一个线程维护一个相应的对象。
代码示例:
/** * 手写一个公平锁 */ public class MyFair { private boolean islock; private Thread lockThread; /** * 先用list代替一下双端链表 */ private List<WaitNotifyNode> waitThreads = new ArrayList<>(); public void lock() { //如果被锁,表示有线程正在运行。 while (islock) { WaitNotifyNode wnn = new WaitNotifyNode(); synchronized (this) { waitThreads.add(wnn); } wnn.waitThread(); //wait方法,仅仅释放监视锁,而不会释放上层锁(即:lock方法,如果加锁,则会一直锁定。) } islock = true; } public void unLock() { islock = false; System.out.println(Thread.currentThread().getName() + ",unlock"); synchronized (this) { if (waitThreads.size() > 0) { waitThreads.get(0).notifyThread(); waitThreads.remove(0); } } } public static void main(String[] args) { MethodFair mf = new MethodFair(); new Thread( () -> mf.a(), "thread-1").start(); new Thread( () -> mf.a(), "thread-2").start(); } } class MethodFair { MyFair myFair = new MyFair(); public void a() { myFair.lock(); System.out.println(Thread.currentThread().getName() + ",A"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ",end!"); myFair.unLock(); } } /** * wait,notify线程类 */ class WaitNotifyNode { public synchronized void waitThread() { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized void notifyThread() { this.notify(); } }