java非公平锁_Java多线程 -- 公平锁和非公平锁的一些思考
在java的鎖機制中,公平和非公平的參考物是什么,個人而言覺得是相對產生的結果而立,簡單的來說,如果一個線程組里,能保證每個線程都能拿到鎖,那么這個鎖就是公平鎖。相反,如果保證不了每個線程都能拿到鎖,也就是存在有線程餓死,那么這個鎖就是非公平鎖。本文圍繞ReenTrantLock來講。
實現原理
那如何能保證每個線程都能拿到鎖呢,隊列FIFO是一個完美的解決方案,也就是先進先出,java的ReenTrantLock也就是用隊列實現的公平鎖和非公平鎖。
在公平的鎖中,如果有另一個線程持有鎖或者有其他線程在等待隊列中等待這個所,那么新發出的請求的線程將被放入到隊列中。而非公平鎖上,只有當鎖被某個線程持有時,新發出請求的線程才會被放入隊列中(此時和公平鎖是一樣的)。所以,它們的差別在于非公平鎖會有更多的機會去搶占鎖。
公平鎖:
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
#hasQueuedPredecessors的實現
public final boolean hasQueuedPredecessors() {
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
非公平鎖:
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
示例
公平鎖:
package com.thread.fair;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by Fant.J.
*/
public class MyFairLock {
/**
* true 表示 ReentrantLock 的公平鎖
*/
private ReentrantLock lock = new ReentrantLock(true);
public void testFail(){
try {
lock.lock();
System.out.println(Thread.currentThread().getName() +"獲得了鎖");
}finally {
lock.unlock();
}
}
public static void main(String[] args) {
MyFairLock fairLock = new MyFairLock();
Runnable runnable = () -> {
System.out.println(Thread.currentThread().getName()+"啟動");
fairLock.testFail();
};
Thread[] threadArray = new Thread[10];
for (int i=0; i<10; i++) {
threadArray[i] = new Thread(runnable);
}
for (int i=0; i<10; i++) {
threadArray[i].start();
}
}
}
Thread-0啟動
Thread-0獲得了鎖
Thread-1啟動
Thread-1獲得了鎖
Thread-2啟動
Thread-2獲得了鎖
Thread-3啟動
Thread-3獲得了鎖
Thread-4啟動
Thread-4獲得了鎖
Thread-5啟動
Thread-5獲得了鎖
Thread-6啟動
Thread-6獲得了鎖
Thread-8啟動
Thread-8獲得了鎖
Thread-7啟動
Thread-7獲得了鎖
Thread-9啟動
Thread-9獲得了鎖
可以看到,獲取鎖的線程順序正是線程啟動的順序。
非公平鎖:
/**
* Created by Fant.J.
*/
public class MyNonfairLock {
/**
* false 表示 ReentrantLock 的非公平鎖
*/
private ReentrantLock lock = new ReentrantLock(false);
public void testFail(){
try {
lock.lock();
System.out.println(Thread.currentThread().getName() +"獲得了鎖");
}finally {
lock.unlock();
}
}
public static void main(String[] args) {
MyNonfairLock nonfairLock = new MyNonfairLock();
Runnable runnable = () -> {
System.out.println(Thread.currentThread().getName()+"啟動");
nonfairLock.testFail();
};
Thread[] threadArray = new Thread[10];
for (int i=0; i<10; i++) {
threadArray[i] = new Thread(runnable);
}
for (int i=0; i<10; i++) {
threadArray[i].start();
}
}
}
Thread-1啟動
Thread-0啟動
Thread-0獲得了鎖
Thread-1獲得了鎖
Thread-8啟動
Thread-8獲得了鎖
Thread-3啟動
Thread-3獲得了鎖
Thread-4啟動
Thread-4獲得了鎖
Thread-5啟動
Thread-2啟動
Thread-9啟動
Thread-5獲得了鎖
Thread-2獲得了鎖
Thread-9獲得了鎖
Thread-6啟動
Thread-7啟動
Thread-6獲得了鎖
Thread-7獲得了鎖
可以看出非公平鎖對鎖的獲取是亂序的,即有一個搶占鎖的過程。
最后
那非公平鎖和公平鎖適合什么場合使用呢,他們的優缺點又是什么呢?
優缺點:
非公平鎖性能高于公平鎖性能。首先,在恢復一個被掛起的線程與該線程真正運行之間存在著嚴重的延遲。而且,非公平鎖能更充分的利用cpu的時間片,盡量的減少cpu空閑的狀態時間。
使用場景
使用場景的話呢,其實還是和他們的屬性一一相關,舉個栗子:如果業務中線程占用(處理)時間要遠長于線程等待,那用非公平鎖其實效率并不明顯,但是用公平鎖會給業務增強很多的可控制性。
總結
以上是生活随笔為你收集整理的java非公平锁_Java多线程 -- 公平锁和非公平锁的一些思考的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑0x0000004e蓝屏代码如何解决
- 下一篇: 梦的光点作弊码大全