線程饑餓
線程饑餓是指線程一直無法獲得所需要的資源導(dǎo)致任務(wù)一直無法執(zhí)行的一種活性故障。
線程饑餓的一個(gè)典型例子就是在高爭用環(huán)境中使用非公平模式的讀寫鎖.讀寫鎖默認(rèn)情況下采用非公平調(diào)度模式,如果這些線程對(duì)鎖的爭用程度比較高,有可能會(huì)出現(xiàn)讀鎖總是搶先執(zhí)行,而寫鎖始終無法獲得的情況,導(dǎo)致一直無法更新數(shù)據(jù).非公平鎖可以支持更高的吞吐率,也可能導(dǎo)致某些線程始終無法獲得資源鎖。
在高爭用環(huán)境中,由于線程優(yōu)先級(jí)設(shè)置不當(dāng),可能會(huì)導(dǎo)致優(yōu)先級(jí)低的線程一直無法獲得CPU執(zhí)行權(quán),出現(xiàn)了線程饑餓的情況。
package com.wkcto.threadactivity.starvation;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 線程饑餓
* 由于線程所需要的資源一直無法獲得導(dǎo)致線程一直處于等待狀態(tài)
*/
public class Test {
public static void main(String[] args) {
//創(chuàng)建只有一個(gè)線程的線程池
ExecutorService executorService = Executors.newSingleThreadExecutor();
//向線程池中添加取數(shù)據(jù)任務(wù)與添加數(shù)據(jù)的任務(wù)
executorService.submit(new TakeDataTask());
executorService.submit(new AddDataTask());
executorService.shutdown();
}
//創(chuàng)建一個(gè)阻塞隊(duì)列
private static final BlockingQueue<Integer> QUEUE = new ArrayBlockingQueue<>(10);
//定義一個(gè)向阻塞隊(duì)列中添加數(shù)據(jù)的任務(wù)
private static class AddDataTask implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getId() + " 編號(hào)的線程執(zhí)行添加數(shù)據(jù)的任務(wù)");
try {
QUEUE.put(123);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//定義從隊(duì)列中取數(shù)據(jù)的任務(wù)
private static class TakeDataTask implements Runnable{
@Override
public void run() {
System.out.println( Thread.currentThread().getId() + " 編號(hào)的線程執(zhí)行取數(shù)據(jù)的任務(wù)");
try {
Integer data = QUEUE.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
活鎖
活鎖是指線程一直處于運(yùn)行狀態(tài),但是任務(wù)卻一直無法進(jìn)展的一種活性故障,即產(chǎn)生活鎖的線程一直做無用功。
線程在爭取所需要的資源過程中,如果”屢戰(zhàn)屢敗,屢敗屢戰(zhàn)”,線程一直在申請(qǐng)其所需要資源而一直未申請(qǐng)成功,那么線程饑餓實(shí)際上就演變?yōu)榛铈i。
類似于兩人過獨(dú)木橋。