• Java多线程中Lock的使用


    Jdk1.5以后,在java.util.concurrent.locks包下,有一组实现线程同步的接口和类,说到线程的同步,可能大家都会想到synchronized关键字,

    这是java内置的关键字,用来处理线程同步的,但这个关键字有很多的缺陷,使用起来也不是很方便和直观,所以就出现了Lock,下面,我们

    就来对比着讲解Lock。

    通常我们在使用synchronized关键字的时候会遇到下面这些问题:

    (1)不可控性,无法做到随心的加锁和释放锁。

    (2)效率比较低下,比如我们现在并发的读两个文件,读与读之间是互不影响的,但如果给这个读的对象使用synchronized来实现同步的话,

    那么只要有一个线程进入了,那么其他的线程都要等待。

    (3)无法知道线程是否获取到了锁。

    而上面synchronized的这些问题,Lock都可以很好的解决,并且jdk1.5以后,还提供了各种锁,例如读写锁,但有一点需要注意,使用synchronized

    关键时,无须手动释放锁,但使用Lock必须手动释放锁。下面我们就来学习一下Lock锁。

    Lock是一个上层的接口,其原型如下,总共提供了6个方法:

    public interface Lock {
      // 用来获取锁,如果锁已经被其他线程获取,则一直等待,直到获取到锁
    void lock();
      // 该方法获取锁时,可以响应中断,比如现在有两个线程,一个已经获取到了锁,另一个线程调用这个方法正在等待锁,但是此刻又不想让这个线程一直在这死等,可以通过
        调用线程的Thread.interrupted()方法,来中断线程的等待过程
      void lockInterruptibly() throws InterruptedException;
      // tryLock方法会返回bool值,该方法会尝试着获取锁,如果获取到锁,就返回true,如果没有获取到锁,就返回false,但是该方法会立刻返回,而不会一直等待
    boolean tryLock();
      // 这个方法和上面的tryLock差不多是一样的,只是会尝试指定的时间,如果在指定的时间内拿到了锁,则会返回true,如果在指定的时间内没有拿到锁,则会返回false
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
      // 释放锁
    void unlock();
      // 实现线程通信,相当于wait和notify,后面会单独讲解
    Condition newCondition();
    }

    那么这几个方法该如何使用了?前面我们说到,使用Lock是需要手动释放锁的,但是如果程序中抛出了异常,那么就无法做到释放锁,有可能引起死锁,

    所以我们在使用Lock的时候,有一种固定的格式,如下:

    Lock l = ...;
    l.lock();
    try {
      // access the resource protected by this lock
    } finally {// 必须使用try,最后在finally里面释放锁
      l.unlock();
    }

    下面我们来看一个简单的例子,代码如下:

    /**
    * 描述:Lock使用
    */
    public class LockDemo {
    // new一个锁对象,注意此处必须声明成类对象,保持只有一把锁,ReentrantLock是Lock的唯一实现类
    Lock lock = new ReentrantLock();
    public void readFile(String fileMessage){
    lock.lock();// 上锁
    try{
    System.out.println(Thread.currentThread().getName()+"得到了锁,正在读取文件……");
    for(int i=0; i<fileMessage.length(); i++){
    System.out.print(fileMessage.charAt(i));
    }
    System.out.println();
    System.out.println("文件读取完毕!");
    }finally{
    System.out.println(Thread.currentThread().getName()+"释放了锁!");
    lock.unlock();
    }
    }

    public void demo(final String fileMessage){
    // 创建若干个线程
    ExecutorService service = Executors.newCachedThreadPool();
    // 提交20个任务
    for(int i=0; i<20; i++){
    service.execute(new Runnable() {
    @Override
    public void run() {
    readFile(fileMessage);
    try {
    Thread.sleep(20);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    });
    }
    // 释放线程池中的线程
    service.shutdown();
    }
    }
  • 相关阅读:
    EasyHLS实现将IPCamera摄像机的RTSP流转成HLS(ts+m3u8)直播输出
    EasyHLS实现将IPCamera摄像机的RTSP流转成HLS(ts+m3u8)直播输出
    EasyHLS实现将IPCamera摄像机的RTSP转HLS直播输出
    基于EasyDarwin云视频平台的幼儿园视频直播(手机直播/微信直播)解决方案
    基于EasyDarwin云视频平台的幼儿园视频直播(手机直播/微信直播)解决方案
    EasyRTMP实现RTMP异步直播推送之环形缓冲区设计
    EasyRTMP实现RTMP异步直播推送之环形缓冲区设计
    EasyRTMP实现的rtmp推流的基本协议流程
    EasyRTMP实现的rtmp推流的基本协议流程
    EasyRTMP实现对接海康、大华等IPCamera SDK进行RTMP推送直播功能
  • 原文地址:https://www.cnblogs.com/junjiang3/p/8733115.html
Copyright © 2020-2023  润新知