Java模擬死鎖發(fā)生之演繹哲學家進餐問題案例詳解
本文實例講述了Java模擬死鎖發(fā)生之演繹哲學家進餐問題。分享給大家供大家參考,具體如下:
一 點睛
常見的死鎖形式:當線程1已經(jīng)占據(jù)資源R1,并持有資源R1上的鎖,而且還在等待資源R2的鎖;而線程2已經(jīng)占據(jù)資源R2,并且持有資源R2上的鎖,卻正在等待資源R1上的鎖。如果兩個線程不釋放自己占據(jù)的資源鎖,而且還申請對方資源上的鎖,申請不到時只能等待,而且它們只能永遠的等待下去。
二 實戰(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("守護線程:程序仍在運行中...");
}
}
}
2 運行
Thread-1拿起了餐刀, 等待叉子......
Thread-2拿起了叉子, 等待餐刀......
守護線程:程序仍在運行中...
守護線程:程序仍在運行中...
守護線程:程序仍在運行中...
守護線程:程序仍在運行中...
守護線程:程序仍在運行中...
三 預防死鎖
1 解決方法
如果規(guī)定線程A和B都必須先拿刀,再拿叉,就不會發(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("守護線程:程序仍在運行中...");
}
}
}
3 運行
Thread-1拿起了餐刀, 等待叉子......
守護線程:程序仍在運行中...
守護線程:程序仍在運行中...
Thread-1又拿起了叉子,吃飯中...
Thread-2拿起了餐刀, 等待叉子......
Thread-2又拿起了叉子,吃飯中...
更多java相關內(nèi)容感興趣的讀者可查看本站專題:《Java進程與線程操作技巧總結》、《Java數(shù)據(jù)結構與算法教程》、《Java操作DOM節(jié)點技巧總結》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對大家java程序設計有所幫助。
相關文章
SpringMVC九大組件之HandlerMapping詳解
這篇文章主要介紹了SpringMVC九大組件之HandlerMapping詳解,HandlerMapping 叫做處理器映射器,它的作用就是根據(jù)當前 request 找到對應的 Handler 和 Interceptor,然后封裝成一個 HandlerExecutionChain 對象返回,需要的朋友可以參考下2023-09-09
SpringBoot項目改為SpringCloud項目使用nacos作為注冊中心的方法
本文主要介紹了SpringBoot項目改為SpringCloud項目使用nacos作為注冊中心,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-04-04
java讀取配置文件(properties)的時候,unicode碼轉utf-8方式
這篇文章主要介紹了java讀取配置文件(properties)的時候,unicode碼轉utf-8方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02

