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 {
            }
        }
    }
    

      

      

  • 相关阅读:
    常见的网络结构
    解决Oracle EM 乱码问题
    Oracle基础
    Unity3D游戏开发初探—2.初步了解3D模型基础
    Unity3D游戏开发初探—1.跨平台的游戏引擎让.NET程序员新生
    Hadoop学习笔记—2.不怕故障的海量存储:HDFS基础入门
    Linux下的.NET之旅:第一站,CentOS+Mono+Xsp构建最简单的ASP.NET服务器
    Hadoop学习笔记—1.基本介绍与环境配置
    f(n-1) + f(n-2)的编译器处理
    C++ 在线编译器(支持 C++11)
  • 原文地址:https://www.cnblogs.com/cnxieyang/p/12751973.html
Copyright © 2011-2022 走看看