模拟死锁发生——演绎哲学家进餐问题

一 点睛

常见的死锁形式:当线程1已经占据资源R1,并持有资源R1上的锁,而且还在等待资源R2的锁;而线程2已经占据资源R2,并且持有资源R2上的锁,却正在等待资源R1上的锁。如果两个线程不释放自己占据的资源锁,而且还申请对方资源上的锁,申请不到时只能等待,而且它们只能永远的等待下去。

二 实战

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 解决方法

如果规定线程A和B都必须先拿刀,再拿叉,就不会发生死锁。

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)