JUC高并发编程
六、多线程锁
6.2)公平锁和非公平锁
6.2.1)代码示例
6.2.1.1)公平锁
以卖票为例进行举例,代码如下:
//第一步 创建资源类,定义属性和和操作方法
class LTicket {
//票数量
private int number = 30;
// 公平锁
private final ReentrantLock lock = new ReentrantLock(true);
//卖票方法
public void sale() {
//上锁
lock.lock();
try {
//判断是否有票
if (number > 0) {
System.out.println(Thread.currentThread().getName() + " :卖出" + (number--) + " 剩余:" + number);
}
} finally {
//解锁
lock.unlock();
}
}
}
public class LSaleTicket {
//第二步 创建多个线程,调用资源类的操作方法
//创建三个线程
public static void main(String[] args) {
LTicket ticket = new LTicket();
// 创建线程 AA
new Thread(() -> {
for (int i = 0; i < 40; i++) {
ticket.sale();
}
}, "AA").start();
// 创建线程 BB
new Thread(() -> {
for (int i = 0; i < 40; i++) {
ticket.sale();
}
}, "BB").start();
// 创建线程 CC
new Thread(() -> {
for (int i = 0; i < 40; i++) {
ticket.sale();
}
}, "CC").start();
}
}
输出:
AA :卖出30 剩余:29
AA :卖出29 剩余:28
AA :卖出28 剩余:27
AA :卖出27 剩余:26
AA :卖出26 剩余:25
AA :卖出25 剩余:24
AA :卖出24 剩余:23
AA :卖出23 剩余:22
AA :卖出22 剩余:21
BB :卖出21 剩余:20
CC :卖出20 剩余:19
AA :卖出19 剩余:18
BB :卖出18 剩余:17
CC :卖出17 剩余:16
AA :卖出16 剩余:15
BB :卖出15 剩余:14
CC :卖出14 剩余:13
AA :卖出13 剩余:12
BB :卖出12 剩余:11
CC :卖出11 剩余:10
AA :卖出10 剩余:9
BB :卖出9 剩余:8
CC :卖出8 剩余:7
AA :卖出7 剩余:6
BB :卖出6 剩余:5
CC :卖出5 剩余:4
AA :卖出4 剩余:3
BB :卖出3 剩余:2
CC :卖出2 剩余:1
AA :卖出1 剩余:0
6.2.1.2)非公平锁
以卖票为例进行举例,代码如下:
//第一步 创建资源类,定义属性和和操作方法
class LTicket {
//票数量
private int number = 30;
// 非公平锁实现一
//private final ReentrantLock lock = new ReentrantLock(false);
// 非公平锁实现二
private final ReentrantLock lock = new ReentrantLock();
//卖票方法
public void sale() {
//上锁
lock.lock();
try {
//判断是否有票
if (number > 0) {
System.out.println(Thread.currentThread().getName() + " :卖出" + (number--) + " 剩余:" + number);
}
} finally {
//解锁
lock.unlock();
}
}
}
public class LSaleTicket {
//第二步 创建多个线程,调用资源类的操作方法
//创建三个线程
public static void main(String[] args) {
LTicket ticket = new LTicket();
// 创建线程 AA
new Thread(() -> {
for (int i = 0; i < 40; i++) {
ticket.sale();
}
}, "AA").start();
// 创建线程 BB
new Thread(() -> {
for (int i = 0; i < 40; i++) {
ticket.sale();
}
}, "BB").start();
// 创建线程 CC
new Thread(() -> {
for (int i = 0; i < 40; i++) {
ticket.sale();
}
}, "CC").start();
}
}
输出:
AA :卖出30 剩余:29
AA :卖出29 剩余:28
AA :卖出28 剩余:27
AA :卖出27 剩余:26
AA :卖出26 剩余:25
AA :卖出25 剩余:24
AA :卖出24 剩余:23
AA :卖出23 剩余:22
AA :卖出22 剩余:21
AA :卖出21 剩余:20
AA :卖出20 剩余:19
AA :卖出19 剩余:18
AA :卖出18 剩余:17
AA :卖出17 剩余:16
AA :卖出16 剩余:15
AA :卖出15 剩余:14
AA :卖出14 剩余:13
AA :卖出13 剩余:12
AA :卖出12 剩余:11
AA :卖出11 剩余:10
AA :卖出10 剩余:9
AA :卖出9 剩余:8
AA :卖出8 剩余:7
AA :卖出7 剩余:6
AA :卖出6 剩余:5
AA :卖出5 剩余:4
AA :卖出4 剩余:3
AA :卖出3 剩余:2
AA :卖出2 剩余:1
AA :卖出1 剩余:0
6.2.2)说明
通过上述代码示例,可以发现下列特点:
6.2.2.1)公平锁
对于线程来说,是阳光普照性质的,所以线程都有执行到的机会,不会发生线程饿死的情况,但执行效率相对较低
// 公平锁 private final ReentrantLock lock = new ReentrantLock(true);
源码如下:
/**
* Creates an instance of {@code ReentrantLock} with the
* given fairness policy.
*
* @param fair {@code true} if this lock should use a fair ordering policy
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
6.2.2.2)非公平锁
对于线程来说,是竞争性质的,会发生线程饿死的情况,但执行效率相对较高
// 非公平锁实现一
//private final ReentrantLock lock = new ReentrantLock(false);
// 非公平锁实现二
private final ReentrantLock lock = new ReentrantLock();
源码如下:
/**
* Creates an instance of {@code ReentrantLock}.
* This is equivalent to using {@code ReentrantLock(false)}.
*/
public ReentrantLock() {
sync = new NonfairSync();
}
/**
* Creates an instance of {@code ReentrantLock} with the
* given fairness policy.
*
* @param fair {@code true} if this lock should use a fair ordering policy
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}