文章目录
Java 公平锁 & 非公平锁
概述
- 公平:每个线程获取锁的机会是平等的。常见公平锁对象:
new ReentrantLock(true)
、new ReentrantReadWriteLock(true)
等。 - 非公平:每个线程获取锁的机会是不平等的。常见非公平锁对象:
synchronized
、new ReentrantLock(false)
、new ReentrantReadWriteLock(false)
。
论证synchronized是非公平锁
public class Demo {
public static void main(String[] args) {
Task task = new Task();
Thread t1 = new Thread(task, "线程一");
Thread t2 = new Thread(task, "线程二");
Thread t3 = new Thread(task, "线程三");
t1.start();
t2.start();
t3.start();
}
}
class Task implements Runnable {
@Override
public void run() {
while (true) {
synchronized (this) {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
}
}
输出:
线程一
线程一
线程一
线程一
线程一
线程一
......
说明:在一段时间内较大概率输出线程一的信息,说明锁被“线程一”持有,体现了非公平性。
论证ReentrantLock(false)是非公平锁
public class Demo {
public static void main(String[] args) {
Task task = new Task();
Thread t1 = new Thread(task, "线程一");
Thread t2 = new Thread(task, "线程二");
Thread t3 = new Thread(task, "线程三");
t1.start();
t2.start();
t3.start();
}
}
class Task implements Runnable {
private Lock lock = new ReentrantLock(false);
@Override
public void run() {
while (true) {
lock.lock();
try {
Thread.sleep(1000L);
System.out.println(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
输出:
线程三
线程三
线程三
线程三
线程三
......
说明:在一段时间内较大概率执行线程三的信息。
论证ReentrantLock(true)是公平锁
public class Demo {
public static void main(String[] args) {
Task task = new Task();
Thread t1 = new Thread(task, "线程一");
Thread t2 = new Thread(task, "线程二");
Thread t3 = new Thread(task, "线程三");
t1.start();
t2.start();
t3.start();
}
}
class Task implements Runnable {
private Lock lock = new ReentrantLock(true);
@Override
public void run() {
while (true) {
lock.lock();
try {
Thread.sleep(1000L);
System.out.println(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
输出:
线程三
线程一
线程二
线程三
线程一
线程二
线程三
......
说明:均匀的输出三个线程的信息。
判断是否为公平锁
在ReentrantLock
锁中,可以通过ReentrantLock#isFair()
方法判断是否为公平锁。
ReentrantLock lock = new ReentrantLock(true);
System.out.println(lock.isFair()); //true