Java死锁,你学会了吗?

开发 前端
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,他们都无法推进下去。通俗一点就是两个进程都持有资源,但是又想抢对方的资源,互不相让了。

死锁

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,他们都无法推进下去。通俗一点就是两个进程都持有资源,但是又想抢对方的资源,互不相让了。

图片图片

死锁的问题和其他的并发安全问题一样,是概率性的,也就是说,即使存在发生死锁的可能性,也并不是 100% 会发生的。如果每个锁的持有时间很短,那么发生冲突的概率就很低,所以死锁发生的概率也很低。可能每天有几千万次的“获取锁”、“释放锁”操作,在巨量的次数面前,整个系统发生问题的几率就会被放大。

必然死锁例子

public static void main(String[] args) {
    //2个对象2把锁
    //创建2个线程,首先获取自己的对象锁,确保获取了锁,然后去获取对方的锁
    final Object o1 = new Object();
    final Object o2 = new Object();
    Thread thread1 = new Thread(new Runnable() {
        @Override
        public void run() {
            synchronized (o1) {
                System.out.println("thread1获取了o1对象的锁");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("thread1等待o2锁释放...");
                synchronized (o2) {
                    System.out.println("thread1获取了o2对象的锁");
                }
            }
        }
    });
    Thread thread2 = new Thread(new Runnable() {
        @Override
        public void run() {
            synchronized (o2) {
                System.out.println("thread2获取了o2对象的锁");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("thread2等待o1锁释放...");
                synchronized (o1) {
                    System.out.println("thread2获取了o1对象的锁");
                }
            }
        }
    });

    thread1.start();
    thread2.start();
}

运行结果:

thread1获取了o1对象的锁
thread2获取了o2对象的锁
thread2等待o1锁释放...
thread1等待o2锁释放...

可见线程一先上了o1锁,线程二先上了o2锁,然后线程一需要等待线程二的o2锁释放获取到该锁执行完后续代码才能释放o1锁,但线程二也需要等待线程一的o1锁释放获取到该锁执行完后续代码才能释放o2锁。他俩就互相等待,锁死了。

死锁必要条件

  • 互斥:一个资源每次只能被一个进程使用。
  • 请求与保持:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
  • 不剥夺:进程已获得的资源,在末使用完之前,不能强行剥夺。
  • 循环等待:若干进程之间形成一种头尾相接的循环等待资源关系。

避免死锁

加锁顺序(线程按照一定的顺序加锁,规定获取资源需要按照一定顺序)
加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁;第二,可以用Lock中tryLock,尝试拿锁,拿不到不会持续等待)
死锁检测


责任编辑:武晓燕 来源: 沐雨花飞蝶
相关推荐

2022-10-13 08:02:13

死锁运算系统

2024-02-04 00:00:00

Effect数据组件

2023-07-26 13:11:21

ChatGPT平台工具

2023-01-10 08:43:15

定义DDD架构

2023-01-28 09:50:17

java多线程代码

2024-01-18 09:38:00

Java注解JDK5

2024-01-02 12:05:26

Java并发编程

2023-08-01 12:51:18

WebGPT机器学习模型

2023-01-30 09:01:54

图表指南图形化

2022-07-08 09:27:48

CSSIFC模型

2023-10-10 11:04:11

Rust难点内存

2023-12-12 08:02:10

2022-09-26 08:49:11

Java架构CPU

2022-06-16 07:50:35

数据结构链表

2024-03-06 08:28:16

设计模式Java

2023-01-31 08:02:18

2022-12-06 07:53:33

MySQL索引B+树

2023-08-26 21:34:28

Spring源码自定义

2023-07-30 22:29:51

BDDMockitoAssert测试

2024-02-02 11:03:11

React数据Ref
点赞
收藏

51CTO技术栈公众号