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!!!---");
}
}