0
点赞
收藏
分享

微信扫一扫

pdf文件编辑,[增删改查]

_karen 2023-12-06 阅读 30

目录

1. 问题引入

2.死锁问题的概念和原因

 3. 解决死锁问题


1. 问题引入

在学习死锁之前, 我们先观察下面的代码能否输出正确的结果:

运行程序, 能正常输出结果:

这个代码只管上看起来, 好像是有锁冲突的, 此时的 locker 对象已经是加锁的状态, 在尝试对 locker 加锁, 不应该会出现阻塞问题吗?

其实, 问题的关键是,这两次加锁, 其实是在同一个线程上进行的.  由于是同一个线程, 此时锁对象就知道了第二次加锁的线程,  第二次加锁操作就可以直接放行通过, 不会出现阻塞.  这个特性称为 "可重入". 

使用可重入锁, 可以避免代码出现死锁问题, 如果使用的不是可重入锁, 就会出现死锁问题.

2.死锁问题的概念和原因

通常,发生死锁问题需要满足以下四个条件:

死锁的例子:

线程1获取到锁A, 线程2获取到锁B, 接下来, 线程1尝试获取锁 B, 线程2尝试获取锁A, 此时出现了死锁问题:  

package thread;

public class ThreadDemo22 {
    public static void main(String[] args) {
        Object A = new Object();
        Object B = new Object();
        Thread t1 = new Thread(()-> {
           synchronized (A) {
               // sleep 是为了t2时间, 让t2也能拿到 B
               try {
                   Thread.sleep(1000);
               }catch (InterruptedException e) {
                   e.printStackTrace();
               }

               //尝试获取B, 并没有释放 A
               synchronized (B) {
                   System.out.println("t1拿到了两把锁");
               }
           }
        });

        Thread t2 = new Thread(()->{
            synchronized (B) {
                // sleep 是给t1时间, 让t1能拿到 A
                try {
                    Thread.sleep(1000);
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //尝试获取A, 并没有释放 B
                synchronized (A) {
                    System.out.println("t2拿到了两把锁");
                }
            }
        });

        t1.start();
        t2.start();
    }
}

 程序没有任何输出结果:

 3. 解决死锁问题

为了避免死锁问题,可以采取以下策略:

对于死锁例子, 我们可以使两个线程的取锁顺序保持一致:

package thread;

public class ThreadDemo22 {
    public static void main(String[] args) {
        Object A = new Object();
        Object B = new Object();
        Thread t1 = new Thread(()-> {
           synchronized (A) {
               // sleep 是为了t2时间, 让t2也能拿到 B
               try {
                   Thread.sleep(1000);
               }catch (InterruptedException e) {
                   e.printStackTrace();
               }

               //尝试获取B, 并没有释放 A
               synchronized (B) {
                   System.out.println("t1拿到了两把锁");
               }
           }
        });

        Thread t2 = new Thread(()->{
            synchronized (A) {
                // sleep 是给t1时间, 让t1能拿到 A
                try {
                    Thread.sleep(1000);
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //尝试获取A, 并没有释放 B
                synchronized (B) {
                    System.out.println("t2拿到了两把锁");
                }
            }
        });

        t1.start();
        t2.start();
    }
}

 

举报

相关推荐

增删改查

webSQL 增删改查

Python 增删改查

SpringMvc增删改查

DML(增删改查)

ElasticSearch 增删改查

0 条评论