Java模擬死鎖發(fā)生之演繹哲學(xué)家進(jìn)餐問(wèn)題案例詳解
本文實(shí)例講述了Java模擬死鎖發(fā)生之演繹哲學(xué)家進(jìn)餐問(wèn)題。分享給大家供大家參考,具體如下:
一 點(diǎn)睛
常見(jiàn)的死鎖形式:當(dāng)線程1已經(jīng)占據(jù)資源R1,并持有資源R1上的鎖,而且還在等待資源R2的鎖;而線程2已經(jīng)占據(jù)資源R2,并且持有資源R2上的鎖,卻正在等待資源R1上的鎖。如果兩個(gè)線程不釋放自己占據(jù)的資源鎖,而且還申請(qǐng)對(duì)方資源上的鎖,申請(qǐng)不到時(shí)只能等待,而且它們只能永遠(yuǎn)的等待下去。
二 實(shí)戰(zhàn)
1 代碼
public class DeadLockDemo
{
/** knife鎖 */
private static String knife = "餐刀"; //臨界資源
/** fork鎖 */
private static String fork = "叉子"; //臨界資源
public static void main(String[] args)
{
DaemonThread daemonTh = new DaemonThread();
Thread newDaemon = new Thread(daemonTh);
newDaemon.setDaemon(true);
newDaemon.start();
new DeadLockDemo().deadLock();
}
private void deadLock()
{
Thread t1 = new Thread(new Runnable() {
@Override
public void run()
{
synchronized (knife) {
System.out.println(Thread.currentThread().getName() + "拿起了" + knife + ", 等待" + fork + "......");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (fork) {
System.out.println(Thread.currentThread().getName() + "又拿起了" + fork + ",吃飯中...");
}
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (fork) {
System.out.println(Thread.currentThread().getName() + "拿起了" + fork + ", 等待" + knife + "......");
synchronized (knife) {
System.out.println(Thread.currentThread().getName() + "又拿起了" + knife + ",吃飯中...");
}
}
}
});
t1.start();
t2.start();
}
}
class DaemonThread implements Runnable
{
@Override
public void run()
{
while(true)
{
try {
Thread.sleep(1000);
}catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("守護(hù)線程:程序仍在運(yùn)行中...");
}
}
}
2 運(yùn)行
Thread-1拿起了餐刀, 等待叉子......
Thread-2拿起了叉子, 等待餐刀......
守護(hù)線程:程序仍在運(yùn)行中...
守護(hù)線程:程序仍在運(yùn)行中...
守護(hù)線程:程序仍在運(yùn)行中...
守護(hù)線程:程序仍在運(yùn)行中...
守護(hù)線程:程序仍在運(yùn)行中...
三 預(yù)防死鎖
1 解決方法
如果規(guī)定線程A和B都必須先拿刀,再拿叉,就不會(huì)發(fā)生死鎖。
2 代碼
public class DeadLockDemo
{
/** knife鎖 */
private static String knife = "餐刀"; //臨界資源
/** fork鎖 */
private static String fork = "叉子"; //臨界資源
public static void main(String[] args)
{
DaemonThread daemonTh = new DaemonThread();
Thread newDaemon = new Thread(daemonTh);
newDaemon.setDaemon(true);
newDaemon.start();
new DeadLockDemo().deadLock();
}
private void deadLock()
{
Thread t1 = new Thread(new Runnable() {
@Override
public void run()
{
synchronized (knife) {
System.out.println(Thread.currentThread().getName() + "拿起了" + knife + ", 等待" + fork + "......");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (fork) {
System.out.println(Thread.currentThread().getName() + "又拿起了" + fork + ",吃飯中...");
}
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (knife) {
System.out.println(Thread.currentThread().getName() + "拿起了" + knife + ", 等待" + fork + "......");
synchronized (fork) {
System.out.println(Thread.currentThread().getName() + "又拿起了" + fork + ",吃飯中...");
}
}
}
});
t1.start();
t2.start();
}
}
class DaemonThread implements Runnable
{
@Override
public void run()
{
while(true)
{
try {
Thread.sleep(1000);
}catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("守護(hù)線程:程序仍在運(yùn)行中...");
}
}
}
3 運(yùn)行
Thread-1拿起了餐刀, 等待叉子......
守護(hù)線程:程序仍在運(yùn)行中...
守護(hù)線程:程序仍在運(yùn)行中...
Thread-1又拿起了叉子,吃飯中...
Thread-2拿起了餐刀, 等待叉子......
Thread-2又拿起了叉子,吃飯中...
更多java相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java進(jìn)程與線程操作技巧總結(jié)》、《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點(diǎn)技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對(duì)大家java程序設(shè)計(jì)有所幫助。
相關(guān)文章
java web實(shí)現(xiàn)簡(jiǎn)單聊天室
這篇文章主要為大家詳細(xì)介紹了java-web實(shí)現(xiàn)簡(jiǎn)單聊天室,含拍一拍功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11
SpringMVC九大組件之HandlerMapping詳解
這篇文章主要介紹了SpringMVC九大組件之HandlerMapping詳解,HandlerMapping 叫做處理器映射器,它的作用就是根據(jù)當(dāng)前 request 找到對(duì)應(yīng)的 Handler 和 Interceptor,然后封裝成一個(gè) HandlerExecutionChain 對(duì)象返回,需要的朋友可以參考下2023-09-09
SpringBoot項(xiàng)目改為SpringCloud項(xiàng)目使用nacos作為注冊(cè)中心的方法
本文主要介紹了SpringBoot項(xiàng)目改為SpringCloud項(xiàng)目使用nacos作為注冊(cè)中心,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04
IDEA如何自動(dòng)生成serialVersionUID的設(shè)置
這篇文章主要介紹了IDEA如何自動(dòng)生成 serialVersionUID 的設(shè)置,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
java讀取配置文件(properties)的時(shí)候,unicode碼轉(zhuǎn)utf-8方式
這篇文章主要介紹了java讀取配置文件(properties)的時(shí)候,unicode碼轉(zhuǎn)utf-8方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02

