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

拼搏现实的明天。 2021-09-29 14:02 425阅读 0赞

一 点睛

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

二 实战

1 代码

  1. public class DeadLockDemo
  2. {
  3. /** knife锁 */
  4. private static String knife = "餐刀"; //临界资源
  5. /** fork锁 */
  6. private static String fork = "叉子"; //临界资源
  7. public static void main(String[] args)
  8. {
  9. DaemonThread daemonTh = new DaemonThread();
  10. Thread newDaemon = new Thread(daemonTh);
  11. newDaemon.setDaemon(true);
  12. newDaemon.start();
  13. new DeadLockDemo().deadLock();
  14. }
  15. private void deadLock()
  16. {
  17. Thread t1 = new Thread(new Runnable() {
  18. @Override
  19. public void run()
  20. {
  21. synchronized (knife) {
  22. System.out.println(Thread.currentThread().getName() + "拿起了" + knife + ", 等待" + fork + "......");
  23. try {
  24. Thread.sleep(2000);
  25. } catch (InterruptedException e) {
  26. e.printStackTrace();
  27. }
  28. synchronized (fork) {
  29. System.out.println(Thread.currentThread().getName() + "又拿起了" + fork + ",吃饭中...");
  30. }
  31. }
  32. }
  33. });
  34. Thread t2 = new Thread(new Runnable() {
  35. @Override
  36. public void run() {
  37. synchronized (fork) {
  38. System.out.println(Thread.currentThread().getName() + "拿起了" + fork + ", 等待" + knife + "......");
  39. synchronized (knife) {
  40. System.out.println(Thread.currentThread().getName() + "又拿起了" + knife + ",吃饭中...");
  41. }
  42. }
  43. }
  44. });
  45. t1.start();
  46. t2.start();
  47. }
  48. }
  49. class DaemonThread implements Runnable
  50. {
  51. @Override
  52. public void run()
  53. {
  54. while(true)
  55. {
  56. try {
  57. Thread.sleep(1000);
  58. }catch (InterruptedException e) {
  59. e.printStackTrace();
  60. }
  61. System.out.println("守护线程:程序仍在运行中...");
  62. }
  63. }
  64. }

2 运行

  1. Thread-1拿起了餐刀, 等待叉子......
  2. Thread-2拿起了叉子, 等待餐刀......
  3. 守护线程:程序仍在运行中...
  4. 守护线程:程序仍在运行中...
  5. 守护线程:程序仍在运行中...
  6. 守护线程:程序仍在运行中...
  7. 守护线程:程序仍在运行中...

三 预防死锁

1 解决方法

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

2 代码

  1. public class DeadLockDemo
  2. {
  3. /** knife锁 */
  4. private static String knife = "餐刀"; //临界资源
  5. /** fork锁 */
  6. private static String fork = "叉子"; //临界资源
  7. public static void main(String[] args)
  8. {
  9. DaemonThread daemonTh = new DaemonThread();
  10. Thread newDaemon = new Thread(daemonTh);
  11. newDaemon.setDaemon(true);
  12. newDaemon.start();
  13. new DeadLockDemo().deadLock();
  14. }
  15. private void deadLock()
  16. {
  17. Thread t1 = new Thread(new Runnable() {
  18. @Override
  19. public void run()
  20. {
  21. synchronized (knife) {
  22. System.out.println(Thread.currentThread().getName() + "拿起了" + knife + ", 等待" + fork + "......");
  23. try {
  24. Thread.sleep(2000);
  25. } catch (InterruptedException e) {
  26. e.printStackTrace();
  27. }
  28. synchronized (fork) {
  29. System.out.println(Thread.currentThread().getName() + "又拿起了" + fork + ",吃饭中...");
  30. }
  31. }
  32. }
  33. });
  34. Thread t2 = new Thread(new Runnable() {
  35. @Override
  36. public void run() {
  37. synchronized (knife) {
  38. System.out.println(Thread.currentThread().getName() + "拿起了" + knife + ", 等待" + fork + "......");
  39. synchronized (fork) {
  40. System.out.println(Thread.currentThread().getName() + "又拿起了" + fork + ",吃饭中...");
  41. }
  42. }
  43. }
  44. });
  45. t1.start();
  46. t2.start();
  47. }
  48. }
  49. class DaemonThread implements Runnable
  50. {
  51. @Override
  52. public void run()
  53. {
  54. while(true)
  55. {
  56. try {
  57. Thread.sleep(1000);
  58. }catch (InterruptedException e) {
  59. e.printStackTrace();
  60. }
  61. System.out.println("守护线程:程序仍在运行中...");
  62. }
  63. }
  64. }

3 运行

  1. Thread-1拿起了餐刀, 等待叉子......
  2. 守护线程:程序仍在运行中...
  3. 守护线程:程序仍在运行中...
  4. Thread-1又拿起了叉子,吃饭中...
  5. Thread-2拿起了餐刀, 等待叉子......
  6. Thread-2又拿起了叉子,吃饭中...

发表评论

表情:
评论列表 (有 0 条评论,425人围观)

还没有评论,来说两句吧...

相关阅读

    相关 哲学家进餐问题

    五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在桌子上有五只碗和五只筷子,他们的生活方式是交替地进行思考和进餐。平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷

    相关 哲学家进餐问题

    一、问题描述 有五个哲学家,他们的生活方式是交替地进行思考和进餐。他们共用一张圆桌,分别坐在五张椅子上。 在圆桌上有五支筷子,平时哲学家进行思考,饥饿时便试图取用其左、