1. 在java中,死鎖形成的原因是
死鎖是進程死鎖的簡稱,是由Dijkstra於1965年研究銀行家演算法時首先提出來的。它是計算機操作系統乃至並發程序設計中最難處理的問題之一。實際上,死鎖問題不僅在計算機系統中存在,在我們日常生活中它也廣泛存在。
1.什麼是死鎖
我們先看看這樣一個生活中的例子:在一條河上有一座橋,橋面較窄,只能容納一輛汽車通過,無法讓兩輛汽車並行。如果有兩輛汽車A和B分別由橋的兩端駛上該橋,則對於A車來說,它走過橋面左面的一段路(即佔有了橋的一部分資源),要想過橋還須等待B車讓出右邊的橋面,此時A車不能前進;對於B車來說,它走過橋面右邊的一段路(即佔有了橋的一部分資源),要想過橋還須等待A車讓出左邊的橋面,此時B車也不能前進。兩邊的車都不倒車,結果造成互相等待對方讓出橋面,但是誰也不讓路,就會無休止地等下去。這種現象就是死鎖。如果把汽車比做進程,橋面作為資源,那麽上述問題就描述為:進程A佔有資源R1,等待進程B佔有的資源Rr;進程B佔有資源Rr,等待進程A佔有的資源R1。而且資源R1和Rr只允許一個進程佔用,即:不允許兩個進程同時佔用。結果,兩個進程都不能繼續執行,若不採取其它措施,這種循環等待狀況會無限期持續下去,就發生了進程死鎖。
在計算機系統中,涉及軟體,硬體資源都可能發生死鎖。例如:系統中只有一台CD-ROM驅動器和一台列印機,某一個進程佔有了CD-ROM驅動器,又申請列印機;另一進程佔有了列印機,還申請CD-ROM。結果,兩個進程都被阻塞,永遠也不能自行解除。
所謂死鎖,是指多個進程循環等待它方佔有的資源而無限期地僵持下去的局面。很顯然,如果沒有外力的作用,那麽死鎖涉及到的各個進程都將永遠處於封鎖狀態。從上面的例子可以看出,計算機系統產生死鎖的根本原因就是資源有限且操作不當。即:一種原因是系統提供的資源太少了,遠不能滿足並發進程對資源的需求。這種競爭資源引起的死鎖是我們要討論的核心。例如:消息是一種臨時性資源。某一時刻,進程A等待進程B發來的消息,進程B等待進程C發來的消息,而進程C又等待進程A發來的消息。消息未到,A,B,C三個進程均無法向前推進,也會發生進程通信上的死鎖。另一種原因是由於進程推進順序不合適引發的死鎖。資源少也未必一定產生死鎖。就如同兩個人過獨木橋,如果兩個人都要先過,在獨木橋上僵持不肯後退,必然會應競爭資源產生死鎖;但是,如果兩個人上橋前先看一看有無對方的人在橋上,當無對方的人在橋上時自己才上橋,那麽問題就解決了。所以,如果程序設計得不合理,造成進程推進的順序不當,也會出現死鎖。
2.產生死鎖的必要條件
從以上分析可見,如果在計算機系統中同時具備下面四個必要條件時,那麽會發生死鎖。換句話說,只要下面四個條件有一個不具備,系統就不會出現死鎖。
〈1〉互斥條件。即某個資源在一段時間內只能由一個進程佔有,不能同時被兩個或兩個以上的進程佔有。這種獨占資源如CD-ROM驅動器,列印機等等,必須在佔有該資源的進程主動釋放它之後,其它進程才能佔有該資源。這是由資源本身的屬性所決定的。如獨木橋就是一種獨占資源,兩方的人不能同時過橋。
〈2〉不可搶占條件。進程所獲得的資源在未使用完畢之前,資源申請者不能強行地從資源佔有者手中奪取資源,而只能由該資源的佔有者進程自行釋放。如過獨木橋的人不能強迫對方後退,也不能非法地將對方推下橋,必須是橋上的人自己過橋後空出橋面(即主動釋放佔有資源),對方的人才能過橋。
〈3〉佔有且申請條件。進程至少已經佔有一個資源,但又申請新的資源;由於該資源已被另外進程佔有,此時該進程阻塞;但是,它在等待新資源之時,仍繼續佔用已佔有的資源。還以過獨木橋為例,甲乙兩人在橋上相遇。甲走過一段橋面(即佔有了一些資源),還需要走其餘的橋面(申請新的資源),但那部分橋面被乙佔有(乙走過一段橋面)。甲過不去,前進不能,又不後退;乙也處於同樣的狀況。
〈4〉循環等待條件。存在一個進程等待序列{P1,P2,...,Pn},其中P1等待P2所佔有的某一資源,P2等待P3所佔有的某一源,......,而Pn等待P1所佔有的的某一資源,形成一個進程循環等待環。就像前面的過獨木橋問題,甲等待乙佔有的橋面,而乙又等待甲佔有的橋面,從而彼此循環等待。
上面我們提到的這四個條件在死鎖時會同時發生。也就是說,只要有一個必要條件不滿足,則死鎖就可以排除。
8.2 死鎖的預防
前面介紹了死鎖發生時的四個必要條件,只要破壞這四個必要條件中的任意一個條件,死鎖就不會發生。這就為我們解決死鎖問題提供了可能。一般地,解決死鎖的方法分為死鎖的預防,避免,檢測與恢復三種(注意:死鎖的檢測與恢復是一個方法)。我們將在下面分別加以介紹。
死鎖的預防是保證系統不進入死鎖狀態的一種策略。它的基本思想是要求進程申請資源時遵循某種協議,從而打破產生死鎖的四個必要條件中的一個或幾個,保證系統不會進入死鎖狀態。
2. 計算機考研難不難
今天天氣很好,在房間里宅久了,准備去客廳散散心。
計算機系是計算機軟硬體相結合,面向系統,側重應用的寬口徑專業。這個專業出來的畢業生一般都被叫做「程序猿」,以高工資和頭禿著稱。但是這個專業出來的考生如果不考研的話,他的就業面會比較的窄,那麼這個專業的考研到底有多難呢?我們下來看看計算機系考研要考哪些科吧。

3. 奼傦細鐢↗AVA璇璦緙栧啓鐨勯摱琛屽剁畻娉曠殑婧愪唬鐮
import java.util.*;
class ThreadTest {
static int type = 4, num = 10; //瀹氫箟璧勬簮鏁扮洰鍜岀嚎紼嬫暟鐩
static int[] resource = new int[type]; //緋葷粺璧勬簮鎬繪暟
//static int[] Resource = new int[type]; //鍓鏈
static Random rand = new Random();
static Bank[] bank = new Bank[num]; //綰跨▼緇
Bank temp = new Bank();
public void init() {
//鍒濆嬪寲緇勪腑姣忎釜綰跨▼錛岄殢鏈哄~鍏呯郴緇熻祫婧愭繪暟
for(int i = 0; i < type; i++)
resource[i] = rand.nextInt(10) + 80;
System.out.print("Resource:");
for(int i = 0; i < type; i++)
System.out.print(" " + resource[i]);
System.out.println("");
for(int i = 0; i < bank.length; i++)
bank[i] = new Bank("#" + i);
}
public ThreadTest4() {
init();
}
class Bank extends Thread {
//閾惰屽剁畻娉曢伩鍏嶆婚攣
public int[]
max = new int[type], //鎬誨叡闇奼傞噺
need = new int[type], //灝氶渶璧勬簮閲
allocation = new int[type]; //宸插垎閰嶉噺
private int[]
request = new int[type], //鐢寵瘋祫婧愰噺
Resource = new int[type]; //璧勬簮鍓鏈
private boolean isFinish = false; //綰跨▼鏄鍚﹀畬鎴
int[][] table = new int[bank.length][type*4]; //浜岀淮璧勬簮鍒嗛厤琛
private void init() {
// 闅忔満濉鍏呮誨叡銆佸皻闇銆佸凡鍒嗛厤閲
synchronized(resource) {
for(int i = 0; i < type; i++) {
max[i] = rand.nextInt(5) + 10;
need[i] = rand.nextInt(10);
allocation[i] = max[i] - need[i];
resource[i] -= allocation[i]; //浠庣郴緇熻祫婧愪腑鍑忓幓宸插垎閰嶇殑
}
printer();
for(int i = 0; i < type; i++) {
if(resource[i] < 0) {
//鑻ュ嚭鐜板凡鍒嗛厤閲忚秴鍑虹郴緇熻祫婧愭繪暟鐨勯敊璇鍒欓鍑
System.out.println("The summation of Threads' allocations is out of range!");
System.exit(1);
}
}
}
}
public Bank(String s) {
setName(s);
init();
start();
}
public Bank() {
//none
}
public void run() {
try {
sleep(rand.nextInt(2000));
}
catch(InterruptedException e) {
throw new RuntimeException(e);
}
while(true) {
//紼嬪簭娌℃湁瀹屾垚鏃朵竴鐩翠笉鏂鐢寵瘋祫婧
if(askFor() == false) {
try {
sleep(1000);
}
catch(InterruptedException e) {
throw new RuntimeException(e);
}
}
else
tryRequest();
if(noNeed() == true)
break;
}
//浼戠湢涓孌墊椂闂存ā鎷熺▼搴忚繍琛
try {
sleep(1000);
}
catch(InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(getName() + " finish!");
synchronized(resource) {
//榪愯岀粨鏉熼噴鏀懼崰鏈夎祫婧
for(int i = 0; i < type; i++) {
resource[i] += allocation[i];
need[i] = allocation[i] = max[i] = 0;
}
}
}
private void printer() {
//鎵撳嵃褰撳墠璧勬簮淇℃伅
System.out.print(getName() + " Max:");
for(int i = 0; i < type; i++)
System.out.print(" " + max[i]);
System.out.print(" Allocation:");
for(int i = 0; i < type; i++)
System.out.print(" " + allocation[i]);
System.out.print(" Need:");
for(int i = 0; i < type; i++)
System.out.print(" " + need[i]);
System.out.print(" Available:");
for(int i = 0; i < type; i++)
System.out.print(" " + resource[i]);
System.out.println("");
}
private boolean askFor() {
//闅忔満浜х敓鐢寵瘋祫婧愰噺騫舵嫻嬫槸鍚﹁秴鏍
boolean canAsk = false;
for(int i = 0; i < type; i++) {
request[i] = rand.nextInt(20);
//闃叉㈢敵璇烽噺瓚呰繃鎵闇閲
if(request[i] > need[i])
request[i] = need[i];
}
for(int i = 0; i < type; i++) //闃叉㈤殢鏈虹敵璇瘋祫婧愬叏涓0
if(request[i] > 0)
canAsk = true;
synchronized(resource) {
//閿佷綇鍙渚涜祫婧愭鏌ユ槸鍚﹁秴鏍
for(int i = 0; i < type; i++) {
if(request[i] > resource[i])
//濡傛灉鐢寵瘋祫婧愯秴榪囧彲渚涜祫婧愬垯絳夊緟涓孌墊椂闂村悗閲嶆柊鐢寵
return false;
}
}
return canAsk;
}
private void tryRequest() {
//鍒涘緩鍓鏈灝濊瘯鍒嗛厤璇鋒眰
synchronized(resource) {
for(int i = 0; i < type; i++)
//渚濈劧瑕侀槻姝㈣鋒眰閲忚秴鍑鴻寖鍥
if(request[i] > resource[i])
return;
for(int i = 0; i < type; i++) {
//澶嶅埗璧勬簮閲忓苟鍑忓幓闇奼傞噺鍒頒竴涓鍓鏈涓
Resource[i] = resource[i];
Resource[i] -= request[i];
}
System.out.print(getName() + " ask for:");
for(int i = 0; i < type; i++)
System.out.print(" " + request[i]);
System.out.println("");
if(checkSafe() == true) {
//濡傛灉媯鏌ュ畨鍏ㄥ垯灝嗗壇鏈鍊艱祴緇欒祫婧愰噺騫朵慨鏀瑰崰鏈夐噺鍜岄渶奼傞噺
for(int i = 0; i < type; i++) {
resource[i] = Resource[i];
allocation[i] += request[i];
need[i] -= request[i];
}
System.out.println(getName() + " request succeed!");
}
else
System.out.println(getName() + " request fail!");
}
}
private boolean checkSafe() {
//閾惰屽剁畻娉曟鏌ュ畨鍏ㄦ
synchronized(bank) {
//灝嗙嚎紼嬭祫婧愪俊鎮鏀懼叆浜岀淮璧勬簮鍒嗛厤琛ㄦ鏌ュ畨鍏ㄦэ紝0~type鍙鐢ㄨ祫婧愶紡type~type*2鎵闇璧勬簮錛弔ype*2~type*3鍗犳湁璧勬簮錛弔ype*3~-1鍙鐢+鍗犵敤璧勬簮
for(int i = 0; i < bank.length; i++) {
for(int j = type; j < type*2; j++) {
table[i][j] = bank[i].need[j%type];
}
for(int j = type*2; j < type*3; j++) {
table[i][j] = bank[i].allocation[j%type];
}
}
//鍐掓場鎺掑簭鎸夐渶奼傝祫婧愪粠灝忓埌澶ф帓
for(int i = 0; i < bank.length; i++) {
for(int j = i; j < bank.length-1; j++) {
sort(j, 4);
}
}
//榪涜屾ゆ椂鍒葷殑瀹夊叏鎬ф鏌
for(int i = 0; i < type; i++) {
table[0][i] = Resource[i];
table[0][i+type*3] = table[0][i] + table[0][i+type*2];
if(table[0][i+type*3] < table[1][i+type])
return false;
}
for(int j = 1; j < bank.length-1; j++) {
for(int k = 0; k < type; k++) {
table[j][k] = table[j-1][k+type*3];
table[j][k+type*3] = table[j][k] + table[j][k+type*2];
if(table[j][k+type*3] < table[j+1][k+type])
return false;
}
}
}
return true;
}
private void sort(int j, int k) {
//閫掑綊鍐掓場鎺掑簭
int tempNum;
if(table[j][k] > table[j+1][k]) {
for(int i = type; i < type*2; i++) {
tempNum = table[j][i];
table[j][i] = table[j+1][i];
table[j+1][i] = tempNum;
}
/*temp = bank[j];
bank[j] = bank[j+1];
bank[j+1] = temp;*/
}
else if(table[j][k] == table[j+1][k] && k < type*2) //姝よ祫婧愰噺鐩稿悓鏃墮掑綊涓嬩竴涓璧勬簮閲忔帓搴忓苟涓旈槻姝㈣秴鍑鴻寖鍥
sort(j, k+1);
}
private boolean noNeed() {
//鏄鍚﹁繕闇瑕佽祫婧
boolean finish = true;
for(int i = 0; i < type; i++) {
if(need[i] != 0) {
finish = false;
break;
}
}
return finish;
}
}
public static void main(String[] args) {
ThreadTest t = new ThreadTest();
//鍚庡彴綰跨▼錛岃懼畾紼嬪簭榪愯屽氶暱鏃墮棿鍚庤嚜鍔ㄧ粨鏉
new Timeout(30000, "---Stop!!!---");
}
}