zoukankan      html  css  js  c++  java
  • Lock锁-Lock接口

    本文从以下几个方面介绍Lock接口,分别从lock锁的介绍、为什么要用lock锁、方法介绍、可见性保证

    Lock接口简介

      Lock锁是一种工具,用来控制对共享资源的访问。

      Lock锁和Synchronized锁两者各个有各自的使用场景,lock并不是来替换Synchronized锁的。

      Lock接口最常见的实现类是ReentrantLock

    Lock接口方法

      lock接口中包含如下四个方法,分别是:lock()、tryLock()、tryLock(long time,TimeUnit unit)和lockInterruptibly(),接下来会详细介绍这四种方法是如何使用的,见下所示。

    lock method

      lock方法是普通的获取锁的方法,lock方法不会像synchronized方法一样在异常发生时自动释放锁,lock方法需要手动释放锁。所以在使用lock锁时一定要手动释放锁。

      见下面的实现,如下

      

    package com.yang.lock;
    
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * lock不会自动释放锁,我们采用try -finally的方式实现,必须手动释放锁
     */
    public class MustUnlock {
        private static Lock lock=new ReentrantLock();
    
        public static void main(String[] args) {
            lock.tryLock();
            try{
                //制定锁定的资源,我们可以采用模拟的方式实现
                System.out.println(Thread.currentThread().getName());
            }finally {
                lock.unlock();
            }
        }
    }
    

      使用lock方法时,当产生死锁时,会永久等待,即为lock锁的弊端。所有有个tryLock的方法,接下来我们一起看下tryLock方法

    tryLock method

       tryLock此方法用来尝试获取锁,如果当前锁没有被其他线程占用的时候,才是可以获取成功的,该方法的返回值为True,若返回False则说明锁没有获取成功

     

    tryLock(long time,TimeUnit unit) method

         此方法相比上面方法多了尝试锁的等待时间,下实例模拟两个线程获取两把锁,见下代码。

       

    package com.yang.lock;
    
    import java.util.Random;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * 尝试获取锁,若能获取到锁,则返回true,否则返回false
     * 用来避免死锁问题
     * 某次的运行结果如下:
     * 线程2取到了锁1
     * 线程1取到了锁1
     * 线程1获取锁2失败了,已经重试了
     * 线程2获取到了锁2
     * 线程2成功获取了两把锁
     * 线程1取到了锁1
     * 线程1获取到了锁2
     * 线程1成功获取了两把锁
     *
     * Process finished with exit code 0
     */
    public class TryDeadLock implements Runnable {
        private static Lock lock1 = new ReentrantLock();
        private static Lock lock2 = new ReentrantLock();
        int flag = 1;
    
        public static void main(String[] args) {
            TryDeadLock tryDeadLock1=new TryDeadLock();
            tryDeadLock1.flag=0;
            TryDeadLock tryDeadLock2=new TryDeadLock();
            tryDeadLock2.flag=1;
            new Thread(tryDeadLock1).start();
            new Thread(tryDeadLock2).start();
    
        }
        @Override
        public void run() {
            //模拟实现死锁
            for (int i = 0; i < 100; i++) {
                if (flag == 1) {
                    try {
                        if (lock1.tryLock(800, TimeUnit.MILLISECONDS)) {
                            try {
                                System.out.println("线程1取到了锁1");
                                Thread.sleep(new Random().nextInt(1000));
                                if (lock2.tryLock(800, TimeUnit.MILLISECONDS)) {
                                    try {
                                        System.out.println("线程1获取到了锁2");
                                        System.out.println("线程1成功获取了两把锁");
                                        break;
    
                                    } finally {
                                        lock2.unlock();
                                    }
                                } else {
                                    System.out.println("线程1获取锁2失败了,已经重试了");
                                }
                            } finally {
                                lock1.unlock();
                                Thread.sleep(new Random().nextInt(1000));
                            }
                        } else {
                            System.out.println("线程1获取锁1失败了,已经重试了");
                        }
                    } catch (Exception e) {
    
                    } finally {
    
                    }
                } else {
                    try {
                        if (lock2.tryLock(3000, TimeUnit.MILLISECONDS)) {
                            try {
                                System.out.println("线程2取到了锁1");
                                Thread.sleep(new Random().nextInt(1000));
                                if (lock1.tryLock(800, TimeUnit.MILLISECONDS)) {
                                    try {
                                        System.out.println("线程2获取到了锁2");
                                        System.out.println("线程2成功获取了两把锁");
                                        break;
    
                                    } finally {
                                        lock1.unlock();
                                    }
                                } else {
                                    System.out.println("线程2获取锁2失败了,已经重试了");
                                }
                            } finally {
                                lock2.unlock();
                                Thread.sleep(new Random().nextInt(1000));
                            }
                        } else {
                            System.out.println("线程2获取锁1失败了,已经重试了");
                        }
                    } catch (Exception e) {
    
                    } finally {
    
                    }
                }
            }
        }
    }
    

      

    lockInterruptibly method

      相当于把try的等待时间设置为无限时间,但是可以被中断,下文通过代码的方式去演示。如下所示。

      

    package com.yang.lock;
    
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * 演示加锁的等待时间为无限制,但是是可以被中断的
     */
    public class LockInterruptiblyTest implements Runnable {
        private Lock lock = new ReentrantLock();
    
        public static void main(String[] args) {
            LockInterruptiblyTest lockInterruptiblyTest=new LockInterruptiblyTest();
            Thread thread0 =new Thread(lockInterruptiblyTest);
            Thread thread1 =new Thread(lockInterruptiblyTest);
            thread0.start();
            thread1.start();
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            thread1.interrupt();
        }
    
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "尝试获取锁");
            try {
                lock.lockInterruptibly();
                try {
                    System.out.println(Thread.currentThread().getName() + "拿到了锁");
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    System.out.println(Thread.currentThread().getName() + "睡眠期间中断了");
                } finally {
                    System.out.println(Thread.currentThread().getName() + "释放了锁");
                }
    
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName()+"等锁期间被中断了");
    
            } finally {
            }
        }
    }
    

      

      

  • 相关阅读:
    java中的 equals 与 ==
    String类的内存分配
    SVN用命令行更换本地副本IP地址
    npoi 设置单元格格式
    net core 微服务框架 Viper 调用链路追踪
    打不死的小强 .net core 微服务 快速开发框架 Viper 限流
    net core 微服务 快速开发框架 Viper 初体验20201017
    Anno 框架 增加缓存、限流策略、事件总线、支持 thrift grpc 作为底层传输
    net core 微服务 快速开发框架
    Viper 微服务框架 编写一个hello world 插件02
  • 原文地址:https://www.cnblogs.com/cnxieyang/p/12751973.html
Copyright © 2011-2022 走看看