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

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

4.3 解决方案2:轮询锁


轮询锁是通过打破“请求和保持条件”来避免造成死锁的,它的实现思路简单来说就是通过轮询来尝试获取锁,如果有一个锁获取失败,则释放当前线程拥有的所有锁,等待下一轮再尝试获取锁。


轮询锁的实现需要使用到 ReentrantLock 的 tryLock 方法,具体实现代码如下:


import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
publicclass SolveDeadLockExample {
    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);
            }
        });
        t1.start(); // 运行线程
        // 创建线程 2
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                lockB.lock(); // 加锁
                System.out.println("线程 2:获取到锁 B!");
                try {
                    Thread.sleep(1000);
                    System.out.println("线程 2:等待获取 A...");
                    lockA.lock(); // 加锁
                    try {
                        System.out.println("线程 2:获取到锁 A!");
                    } finally {
                        lockA.unlock(); // 释放锁
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lockB.unlock(); // 释放锁
                }
            }
        });
        t2.start(); // 运行线程
    }
     /**
     * 轮询锁
     */
    public static void pollingLock(Lock lockA, Lock lockB) {
        while (true) {
            if (lockA.tryLock()) { // 尝试获取锁
                System.out.println("线程 1:获取到锁 A!");
                try {
                    Thread.sleep(1000);
                    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.");
                }
            }
            // 等待一秒再继续执行
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


以上程序的执行结果如下:


image.png


从上述结果可以看出,以上代码也没有出现死锁的问题。

相关文章
|
存储 安全 Java
Java多线程基础——两万字详解
进程简单来说就是正在运行的程序,是可以通过双击执行的.exe文件,打开我们电脑的任务管理器,可以看到我们的电脑正在执行的进程,目前我们的电脑都是多进程模式。
125 0
Java多线程基础——两万字详解
|
缓存 Oracle 安全
2.5W 字详解线程与锁了,面试随便问!!(1)
2.5W 字详解线程与锁了,面试随便问!!(1)
137 0
2.5W 字详解线程与锁了,面试随便问!!(1)
|
存储 安全 Java
2.5W 字详解线程与锁了,面试随便问!!(2)
2.5W 字详解线程与锁了,面试随便问!!(2)
104 0
2.5W 字详解线程与锁了,面试随便问!!(2)
阿粉写了八千多字,就是为了把 ReentrantLock 讲透(三)
啥是可重入锁呢?比如:线程 1 通过调用 lock() 方法获取锁之后,再调用 lock 时,就不会再进行阻塞获取锁,而是直接增加重试次数。 还记得 synchronized 吗?它有 monitorenter 和 monitorexit 两种指令来保证锁,而它们的作用可以理解为每个锁对象拥有一个锁计数器,也就是如果再次调用 lock() 方法,计数器会进行加 1 操作
阿粉写了八千多字,就是为了把 ReentrantLock 讲透(三)
阿粉写了八千多字,就是为了把 ReentrantLock 讲透(一)
啥是可重入锁呢?比如:线程 1 通过调用 lock() 方法获取锁之后,再调用 lock 时,就不会再进行阻塞获取锁,而是直接增加重试次数。 还记得 synchronized 吗?它有 monitorenter 和 monitorexit 两种指令来保证锁,而它们的作用可以理解为每个锁对象拥有一个锁计数器,也就是如果再次调用 lock() 方法,计数器会进行加 1 操作
阿粉写了八千多字,就是为了把 ReentrantLock 讲透(一)
1.3w字,一文详解死锁!(11)
1.3w字,一文详解死锁!(11)
67 0
1.3w字,一文详解死锁!(11)
|
Java Unix Linux
1.3w字,一文详解死锁!(3)
1.3w字,一文详解死锁!(3)
104 0
1.3w字,一文详解死锁!(3)
1.3w字,一文详解死锁!(8)
1.3w字,一文详解死锁!(8)
94 0
1.3w字,一文详解死锁!(8)
1.3w字,一文详解死锁!(12)
1.3w字,一文详解死锁!(12)
88 0
1.3w字,一文详解死锁!(12)
|
运维 监控 Oracle
1.3w字,一文详解死锁!(6)
1.3w字,一文详解死锁!(6)
115 0
1.3w字,一文详解死锁!(6)