• java拓展----Lock锁


    目录

      1.介绍Lock

      2.Lock的基本使用

      3.Lock之线程之间的通信

      4.总结

    一、介绍Lock

      首先先讲一下笔者为什么会涉及到Lock这个东西,使用synchronized来锁对象或方法时,如果被锁的这个方法发生阻塞(sleep),那么将影响锁资源的释放,

    而其他处于等待状态的对象或方法将一直处于等待状态,直到休眠完或阻塞清除,这就带来了一大并发症。而使用Lock则可以解决这一问题。

      Lock与synchronized之间有很多差异:

      1.Lock是一个接口,synchronized则是java中的一个关键字

      2.Lock需要手动释放锁,synchronized不需要手动释放锁

    二、Lock的基本使用

      

    Lock的API

     Lock是一个接口,他需要由ReentrantLock、ReentrantReadWriteLock.ReadLock、ReentrantReadWriteLock.WriteLock来创建

    它主要的方法有:

    ReentrantWriteReadLock是读写锁,它将文件的读和写分开,在这不多做研究。

    如想了解的读者请参考https://blog.csdn.net/zhuhezan/article/details/6613108

    以下是Lock的基本使用:  

    package com.demo.thread;
    
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class LockThread {
        //创建锁对象
        Lock lock = new ReentrantLock(); 
        
        public void lock(String name) {  
            // 获取锁  
            lock.lock();  
            try {  
                System.out.println(name + "获取锁");  
                // 访问此锁保护的资源  
            } finally {  
                // 释放锁  
                lock.unlock();  
                System.out.println(name + "释放锁");  
            }  
        }  
    
        public static void main(String[] args) {
            LockThread lt = new LockThread();
            new Thread(() -> lt.lock("A")).start();
            new Thread(() -> lt.lock("B")).start();
        }
    }

    三、Lock之线程之间的通信

      

      如果我们不使用Lock,要做到线程之间的通信我们需要使用到Object类中的wait、notify、notifyAll方法来控制线程间的通信。在jdk1.5当中,线程之间的通信如果使用Lock接口的话需要使用到newCondition方法来创建需要通信的对象Condition。

    一下是newCondition方法的具体解释:

    Condition对象的方法如下:

    一下是使用condition完成Lock对象线程间的通信Demo:

    package com.demo.condition;
    
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * Condition初次使用
     * 使用Condition控制线程间的通信
     * @author Administrator
     *
     */
    public class ConditionDemo {
        public static void main(String[] args) {
            Output output = new Output();
            for(int i =0;i<2;i++){
            new Thread(new Runnable() {
                public void run() {
                    output.get1(1);
                }
            }).start();
            
            new Thread(new Runnable() {
                public void run() {
                    output.get2(2);
                }
            }).start();
            
            new Thread(new Runnable() {
                public void run() {
                    output.get3(3);
                }
            }).start();
            }
        }
    }
    class Output{
        private int count =1;
        //创建Lock对象
        final Lock lock = new ReentrantLock();
        //创建三个condition对象
        private Condition condition1 = lock.newCondition();
        private Condition condition2 = lock.newCondition();
        private Condition condition3 = lock.newCondition();
        
        public void get1(int i){
            //获取锁资源
            lock.lock();
            System.out.println("condition1已获取锁资源");
            try {
                while(count!=1){
                    condition1.await();
                }
                System.out.println("condition1获取到资源");
                for(int j=0;j<10;j++){
                    System.out.println(i+"正在执行condition1"+j);
                    Thread.sleep(1000);
                }
                count++;
                //唤醒第二个等待的线程
                condition2.signal();
            } catch (InterruptedException e) {
                    e.printStackTrace();
            }finally{
                //释放锁资源,避免锁死状态
                lock.unlock();
            }
            
        }
        public void get2(int i){
            //获取锁资源
            lock.lock();
            System.out.println("condition2已获取锁资源");
            try {
                while(count!=2){
                    condition2.await();
                }
                System.out.println("condition2获取到资源");
                for(int j=0;j<10;j++){
                    System.out.println(i+"正在执行condition2"+j);
                    Thread.sleep(1000);
                }
                count++;
                //唤醒第三个等待的线程
                condition3.signal();
            } catch (InterruptedException e) {
                    e.printStackTrace();
            }finally{
                //释放锁资源,避免锁死状态
                lock.unlock();
            }
            
        }
        public void get3(int i){
            //获取锁资源
            lock.lock();
            System.out.println("condition3已获取锁资源");
            try {
                while(count!=3){
                    condition3.await();
                }
                System.out.println("condition3获取到资源");
                for(int j=0;j<10;j++){
                    System.out.println(i+"正在执行condition3"+j);
                    Thread.sleep(1000);
                }
                count=1;
                //唤醒第一个等待的线程
                condition1.signal();
            } catch (InterruptedException e) {
                    e.printStackTrace();
            }finally{
                //释放锁资源,避免锁死状态
                lock.unlock();
            }
            
        }
    }

     四、总结

      结合以上观点来看,总而言之,使用Lock相对于传统使用synchronized关键字来说,逻辑更清晰,避免了线程等待的并发症。而且

    我们还可以直观的观测到线程之间或去锁的状态。个人还是推荐是用Lock代替synchronized的。

  • 相关阅读:
    云通信
    PullToRefreshGridView上拉刷新,下拉加载
    数据库开源框架GreenDao的使用解析
    RxJava2.0的使用详解
    ButterKnife的使用详解
    Jquery设置完颜色后hover不生效的解决办法
    jquery使用css函数设置背景色无效解决办法
    SpringBoot如何返回页面
    如何创建一个SpringBoot多模块项目
    连接mysql报错java.sql.SQLException: The server time zone value '�й���׼ʱ��' is unrecognized...解决方法
  • 原文地址:https://www.cnblogs.com/bananafish/p/9936903.html
Copyright © 2020-2023  润新知