公平锁与非公平锁 - morris131/morris-book GitHub Wiki

公平锁与非公平锁

公平锁,就是很公平,在并发环境中,每个线程在获取锁时会先查看此锁维护的等待队列,如果为空,或者当前线程是等待队列的第一个,就占有锁,否则就会加入到等待队列中,以后会按照FIFO的规则从队列中取到自己。

非公平锁是不管线程是否是先运行,都是随机获得锁的。

如果在绝对时间上,先对锁进行获取的请求一定先被满足,那么这个锁是公平的,反之,是不公平的。公平的获取锁,也就是等待时间最长的线程最优先获取锁,也可以说锁获取是顺序的。ReentrantLock提供了一个构造函数,能够控制锁是否是公平的。

事实上,公平的锁机制往往没有非公平的效率高,但是,并不是任何场景都是以TPS作为 唯一的指标,公平锁能够减少“饥饿”发生的概率,等待越久的请求越是能够得到优先满足。

公平锁

package com.morris.ch4;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class FairLockTest {

	public static void main(String[] args) {
		
		Service service = new Service(true);
		
		Runnable runnable = new Runnable() {
			
			@Override
			public void run() {
				System.out.println(Thread.currentThread().getName() + "is running");
				service.method();
			}
		};
		
		Thread[] threads = new Thread[10];
		for (int i = 0; i < 10; i++) {
			threads[i] = new Thread(runnable);
		}

		for (int i = 0; i < 10; i++) {
			threads[i].start();
		}
	}

	static class Service {
		
		private Lock lock;

		Service(boolean isFair) {
			lock = new ReentrantLock(isFair);
		}
		
		public void method() {
			lock.lock();
			try {
				System.out.println(Thread.currentThread().getName() + "is get lock");
			} finally {
				lock.unlock();
			}
		}
	}

}


运行结果如下:

Thread-2is running
Thread-1is running
Thread-4is running
Thread-3is running
Thread-0is running
Thread-6is running
Thread-2is get lock
Thread-7is running
Thread-5is running
Thread-8is running
Thread-1is get lock
Thread-9is running
Thread-4is get lock
Thread-3is get lock
Thread-0is get lock
Thread-6is get lock
Thread-7is get lock
Thread-5is get lock
Thread-8is get lock
Thread-9is get lock

非公平锁

package com.morris.ch4;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class FairLockTest {

	public static void main(String[] args) {
		
		Service service = new Service(false);
		
		Runnable runnable = new Runnable() {
			
			@Override
			public void run() {
				System.out.println(Thread.currentThread().getName() + "is running");
				service.method();
			}
		};
		
		Thread[] threads = new Thread[10];
		for (int i = 0; i < 10; i++) {
			threads[i] = new Thread(runnable);
		}

		for (int i = 0; i < 10; i++) {
			threads[i].start();
		}
	}

	static class Service {
		
		private Lock lock;

		Service(boolean isFair) {
			lock = new ReentrantLock(isFair);
		}
		
		public void method() {
			lock.lock();
			try {
				System.out.println(Thread.currentThread().getName() + "is get lock");
			} finally {
				lock.unlock();
			}
		}
	}

}

运行结果如下:

Thread-0is running
Thread-5is running
Thread-6is running
Thread-1is running
Thread-8is running
Thread-3is running
Thread-4is running
Thread-2is running
Thread-7is running
Thread-0is get lock
Thread-6is get lock
Thread-9is running
Thread-9is get lock
Thread-5is get lock
Thread-1is get lock
Thread-8is get lock
Thread-3is get lock
Thread-4is get lock
Thread-2is get lock
Thread-7is get lock

⚠️ **GitHub.com Fallback** ⚠️