饑餓
如果一個(gè)線程因?yàn)镃PU時(shí)間全部被其他線程搶走而得不到CPU運(yùn)行時(shí)間亡哄,這種狀態(tài)被稱之為“饑餓”糊渊。
導(dǎo)致饑餓的原因
- 高優(yōu)先級(jí)線程吞噬所有的低優(yōu)先級(jí)線程的CPU時(shí)間
- 線程被永久堵塞在一個(gè)等待進(jìn)入同步塊的狀態(tài)
- 線程在等待一個(gè)本身也處于永久等待完成的對(duì)象(比如調(diào)用這個(gè)對(duì)象的wait方法)
實(shí)現(xiàn)Java的公平性
- 使用Locks取代Synchronized塊
public class Synchronizer{
Lock lock = new Lock();
public void doSynchronized() throws InterruptedException{
this.lock.lock();
//critical section, do a lot of work which takes a long time
this.lock.unlock();
}
}
public class Lock{
private boolean isLocked = false;
private Thread lockingThread = null;
public synchronized void lock() throws InterruptedException{
while(isLocked){
wait();
}
isLocked = true;
lockingThread = Thread.currentThread();
}
public synchronized void unlock(){
if(this.lockingThread != Thread.currentThread()){
throw new IllegalMonitorStateException(
"Calling thread has not locked this lock");
}
isLocked = false;
lockingThread = null;
notify();
}
}
這個(gè)版本的lock方法和synchronized就公平性而言妓美,沒(méi)有任何區(qū)別
- 使用公平鎖
public class FairLock {
private boolean isLocked = false;
private Thread lockingThread = null;
private List<QueueObject> waitingThreads =
new ArrayList<QueueObject>();
public void lock() throws InterruptedException{
QueueObject queueObject = new QueueObject();
boolean isLockedForThisThread = true;
synchronized(this){
waitingThreads.add(queueObject);
}
while(isLockedForThisThread){
synchronized(this){
isLockedForThisThread =
isLocked || waitingThreads.get(0) != queueObject;
if(!isLockedForThisThread){
isLocked = true;
waitingThreads.remove(queueObject);
lockingThread = Thread.currentThread();
return;
}
}
try{
queueObject.doWait();
}catch(InterruptedException e){
synchronized(this) { waitingThreads.remove(queueObject); }
throw e;
}
}
}
public synchronized void unlock(){
if(this.lockingThread != Thread.currentThread()){
throw new IllegalMonitorStateException(
"Calling thread has not locked this lock");
}
isLocked = false;
lockingThread = null;
if(waitingThreads.size() > 0){
waitingThreads.get(0).doNotify();
}
}
}
public class QueueObject {
private boolean isNotified = false;
public synchronized void doWait() throws InterruptedException {
while(!isNotified){
this.wait();
}
this.isNotified = false;
}
public synchronized void doNotify() {
this.isNotified = true;
this.notify();
}
public boolean equals(Object o) {
return this == o;
}
}
FairLock新創(chuàng)建了一個(gè)QueueObject的實(shí)例柿冲,并對(duì)每個(gè)調(diào)用lock()的線程進(jìn)行入隊(duì)列渗柿。調(diào)用unlock()的線程將從隊(duì)列頭部獲取QueueObject饱亮,并對(duì)其調(diào)用doNotify()矾芙,以喚醒在該對(duì)象上等待的線程。通過(guò)這種方式近上,在同一時(shí)間僅有一個(gè)等待線程獲得喚醒剔宪,而不是所有的等待線程。