1.3w字,一文详解死锁!(13)

简介: 1.3w字,一文详解死锁!(13)

从上述结果可以看出,线程 1(轮询锁)一直未成功获取到锁,造成这种结果的原因是:线程 1 每次轮询的等待时间为固定的 1s,而线程 2 也是相同的频率,每 1s 获取一次锁,这样就会导致线程 2 会一直先成功获取到锁,而线程 1 则会一直处于“饿死”的情况,执行流程如下图所示:


image.png


优化版


接下来,我们可以将轮询锁的固定等待时间,改进为固定时间 + 随机时间的方式,这样就可以避免因为获取锁的频率一致,而造成轮询锁“饿死”的问题了,具体实现代码如下:


import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
publicclass SolveDeadLockExample {
    privatestatic Random rdm = new Random();
    public static void main(String[] args) {
        Lock lockA = new ReentrantLock(); // 创建锁 A
        Lock lockB = new ReentrantLock(); // 创建锁 B
        // 创建线程 1(使用轮询锁)
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                // 调用轮询锁
                pollingLock(lockA, lockB, 3);
            }
        });
        t1.start(); // 运行线程
        // 创建线程 2
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    lockB.lock(); // 加锁
                    System.out.println("线程 2:获取到锁 B!");
                    try {
                        System.out.println("线程 2:等待获取 A...");
                        lockA.lock(); // 加锁
                        try {
                            System.out.println("线程 2:获取到锁 A!");
                        } finally {
                            lockA.unlock(); // 释放锁
                        }
                    } finally {
                        lockB.unlock(); // 释放锁
                    }
                    // 等待一秒之后继续执行
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t2.start(); // 运行线程
    }
    /**
     * 轮询锁
     */
    public static void pollingLock(Lock lockA, Lock lockB, int maxCount) {
        // 循环次数计数器
        int count = 0;
        while (true) {
            if (lockA.tryLock()) { // 尝试获取锁
                System.out.println("线程 1:获取到锁 A!");
                try {
                    Thread.sleep(100); // 等待 0.1s(获取锁需要的时间)
                    System.out.println("线程 1:等待获取 B...");
                    if (lockB.tryLock()) { // 尝试获取锁
                        try {
                            System.out.println("线程 1:获取到锁 B!");
                        } finally {
                            lockB.unlock(); // 释放锁
                            System.out.println("线程 1:释放锁 B.");
                            break;
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lockA.unlock(); // 释放锁
                    System.out.println("线程 1:释放锁 A.");
                }
            }
            // 判断是否已经超过最大次数限制
            if (count++ > maxCount) {
                // 终止循环
                System.out.println("轮询锁获取失败,记录日志或执行其他失败策略");
                return;
            }
            // 等待一定时间(固定时间 + 随机时间)之后再继续尝试获取锁
            try {
                Thread.sleep(300 + rdm.nextInt(8) * 100); // 固定时间 + 随机时间
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}



相关文章
|
算法 安全 Java
Java多线程与并发框(完结篇)——再看不懂我找不到女朋友
Java多线程与并发框(完结篇)——再看不懂我找不到女朋友
62 0
Java多线程与并发框(完结篇)——再看不懂我找不到女朋友
|
存储 安全 Java
Java多线程基础——两万字详解
进程简单来说就是正在运行的程序,是可以通过双击执行的.exe文件,打开我们电脑的任务管理器,可以看到我们的电脑正在执行的进程,目前我们的电脑都是多进程模式。
119 0
Java多线程基础——两万字详解
|
存储 缓存 安全
2w字 + 40张图带你参透并发编程!(一)
在计算机最早期的时候,没有操作系统,执行程序只需要一种方式,那就是从头到尾依次执行。任何资源都会为这个程序服务,在计算机使用某些资源时,其他资源就会空闲,就会存在 浪费资源 的情况。
2w字 + 40张图带你参透并发编程!(一)
1.3w字,一文详解死锁!(9)
1.3w字,一文详解死锁!(9)
96 0
1.3w字,一文详解死锁!(9)
|
Java
1.3w字,一文详解死锁!(14)
1.3w字,一文详解死锁!(14)
110 0
1.3w字,一文详解死锁!(14)
1.3w字,一文详解死锁!(10)
1.3w字,一文详解死锁!(10)
67 0
1.3w字,一文详解死锁!(10)
1.3w字,一文详解死锁!(11)
1.3w字,一文详解死锁!(11)
62 0
1.3w字,一文详解死锁!(11)
1.3w字,一文详解死锁!(7)
1.3w字,一文详解死锁!(7)
76 0
1.3w字,一文详解死锁!(7)
|
Java
1.3w字,一文详解死锁!(5)
1.3w字,一文详解死锁!(5)
111 0
1.3w字,一文详解死锁!(5)
|
监控 Java
1.3w字,一文详解死锁!(4)
1.3w字,一文详解死锁!(4)
88 0
1.3w字,一文详解死锁!(4)