什么是公平和非公平::
公平指的是按照线程的请求顺序,来分配锁;非公平指的是不完全按照请求的顺序,在一定情况下,可以插队
注意::非公平也同样不提倡“插队”行为,这里的非公平指的是“在合适的时机”插队,而不是盲目插队
什么时机合适呢? 火车票被插队的例子 ,自己没准备好买票,上个买票的人回来又问了一句就有了,不影响我正常买票
为什么要有非公平锁?
1. 这样做提高了效率 2. 避免唤醒带来的空档期
公平的情况(以ReentrantLock为例)
如果在创建ReentrantLock对象时,参数填写为true,那么这就是个公平锁,否则是非公平锁
假设线程1234是按顺序调用lock( )的
注意:针对tryLock()方法,它不遵守设定的公平规则;
例如,当有线程执行tryLock()的时候,一旦有线程释放了锁,那么这个正在执行tryLock的线程就能获取到锁,即使在它之前已经有其他正在等待队列的线程
public class FairLock {
// 例子:公平锁,先竞争锁,只有其中一个假设线程4能拿到锁,其他的都只能排队,排队位置在标记(1),当线程4进入临界区后然后
// 随机休眠,当休眠完毕后离开临界区,打印等待队列长度9,因为总共10个线程,线程4出队。排队的第一个线程3进入第一个临界区,但是
// 之前排队的线程没有离开临界区,所以只能等其他的线程打印完后,才能轮到线程4执行第二个临界区代码,线程3离开临界区,打印等待队列
// 长度也是9,因为线程4在第二个临界区等待,进入了等待队列。当都执行完离开第一个临界区后,在第二个临界区最开始等待的线程4开始打印
// 第二个临界区代码
// 非公平锁:可以进行插队,随拿到锁就先执行
public static void main(String[] args) {
PrintQueue printQueue = new PrintQueue();
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.length; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"开始打印");
printQueue.printJob();
System.out.println(Thread.currentThread().getName()+"打印完毕");
}).start();
}
}
// 公平锁,拿不到锁的线程就进行排队,
private static ReentrantLock queueLock = new ReentrantLock(true);
static class PrintQueue{
public void printJob(){
// (1) 被阻塞的线程在此排队
System.out.println("===================>"+queueLock.getQueueLength());
queueLock.lock();
try {
long duration = (long)(Math.random()*6000);
System.out.println(Thread.currentThread().getName()+"正在打印GG, 需要"+(duration/1000)+"秒");
Thread.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
queueLock.unlock();
}
System.out.println("========********===========>"+queueLock.getQueueLength());
queueLock.lock();
try {
long duration = (long)(Math.random()*6000);
System.out.println(Thread.currentThread().getName()+"正在打印, 需要"+(duration/1000));
Thread.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
queueLock.unlock();
}
}
}
}
/** 公平锁
* Thread-0开始打印
* Thread-4开始打印
* ===================>0
* Thread-1开始打印
* Thread-3开始打印
* ===================>0
* Thread-2开始打印
* ===================>0
* Thread-9开始打印
* ===================>0
* Thread-5开始打印
* ===================>3
* Thread-8开始打印
* ===================>4
* ===================>2
* Thread-7开始打印
* ===================>6
* Thread-6开始打印
* ===================>7
* ===================>0
* Thread-4正在打印GG, 需要4秒
* ========********===========>9
* Thread-3正在打印GG, 需要3秒
* ========********===========>9
* Thread-2正在打印GG, 需要2秒
* ========********===========>9
* Thread-0正在打印GG, 需要0秒
* ========********===========>9
* Thread-5正在打印GG, 需要3秒
* ========********===========>9
* Thread-8正在打印GG, 需要1秒
* ========********===========>9
* Thread-9正在打印GG, 需要2秒
* ========********===========>9
* Thread-7正在打印GG, 需要2秒
* ========********===========>9
* Thread-6正在打印GG, 需要1秒
* ========********===========>9
* Thread-1正在打印GG, 需要3秒
* ========********===========>9
* Thread-4正在打印, 需要2
* Thread-4打印完毕
* Thread-3正在打印, 需要5
* Thread-3打印完毕
* Thread-2正在打印, 需要1
* Thread-2打印完毕
* Thread-0正在打印, 需要5
* Thread-0打印完毕
* Thread-5正在打印, 需要4
* Thread-5打印完毕
* Thread-8正在打印, 需要5
* Thread-8打印完毕
* Thread-9正在打印, 需要5
* Thread-9打印完毕
* Thread-7正在打印, 需要1
* Thread-7打印完毕
* Thread-6正在打印, 需要0
* Thread-6打印完毕
* Thread-1正在打印, 需要4
* Thread-1打印完毕
*/