美文网首页
使用 超时时间 来防止死锁

使用 超时时间 来防止死锁

作者: 张云飞Vir | 来源:发表于2021-07-16 18:12 被阅读0次

    1. 背景

    在多线程编程中要用到锁来处理资源的抢占,有可能遇到死锁的情况。

    死锁是指两个或两个以上的进程或者线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种 双方都阻塞的现象。

    2.模拟一个死锁

    示例:两个 lock 对象互相调用导致死锁。

            ReentrantLock lock1 = new ReentrantLock();
            ReentrantLock lock2 = new ReentrantLock();
    
    
    // 吃饼干
            void eating() throws InterruptedException {
                String name = Thread.currentThread().getName();
                lock1.lock();
                System.out.printf("\t\t [Thread: %s] 开始 eating ... \n", name);
    
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                lock2.lock();
              
                System.out.printf("[Thread: %s] 执行完成 \n", name);
                lock1.unlock();
            }
    
            // 喝水
            void drinking() {
                String name = Thread.currentThread().getName();
                lock2.lock();
                System.out.printf("[Thread: %s] 开始 drinking ... \n", name);
    
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                lock1.lock();
    
                System.out.printf("[Thread: %s] 执行完成 \n", name);
                lock2.unlock();
            }
    

    3. 怎么解决?

    /**
    如果在给定的线程中没有其他线程持有锁,则获取锁

    如果锁被另一个线程持有,那么等待锁,直到下面情况发生:
    1、当前线程获取的锁;
    2、当前线程等待超过指定的等待时间

    public boolean tryLock(long timeout, TimeUnit unit)
    

    其中 timeout 是时间,TimeUnit是时间单位(可选分钟,毫秒等)。

    4. 示例

    即把等待锁的时候的代码改为:

      // 带有 超时时间的锁定,当超过指定时间就不在等了
    lock2.tryLock(1000, TimeUnit.MILLISECONDS);
    
    

    完整示例:

    class MainApplicatoin {
    
        static class Desk {
            ReentrantLock lock1 = new ReentrantLock();
            ReentrantLock lock2 = new ReentrantLock();
    
            // 吃饼干
            void eating() throws InterruptedException {
                String name = Thread.currentThread().getName();
                lock1.lock();
                System.out.printf("\t\t [Thread: %s] 开始 eating ... \n", name);
    
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                lock2.lock();
                // 带有 超时时间的锁定,当超过指定时间就不在等了
                // lock2.tryLock(1000, TimeUnit.MILLISECONDS);
    
                System.out.printf("[Thread: %s] 执行完成 \n", name);
                lock1.unlock();
            }
    
            // 喝水
            void drinking() {
                String name = Thread.currentThread().getName();
                lock2.lock();
                System.out.printf("[Thread: %s] 开始 drinking ... \n", name);
    
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                lock1.lock();
    
                System.out.printf("[Thread: %s] 执行完成 \n", name);
                lock2.unlock();
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            Desk desk = new Desk();
    
            Thread thread1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        desk.eating();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            thread1.setName("thread1");
            thread1.start();
    
            Thread thread2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    desk.drinking();
                }
            });
            thread2.setName("thread2");
            thread2.start();
    
    
    //        Thread.sleep(60*1000);
        }
    
    }
    
    

    END

    相关文章

      网友评论

          本文标题:使用 超时时间 来防止死锁

          本文链接:https://www.haomeiwen.com/subject/suvadltx.html