在Java5.0之前,只有synchronized(内置锁)和volatile. Java5.0后引入了显示锁ReentrantLock.

ReentrantLock概况

ReentrantLock是可重入的锁,它不同于内置锁, 它在每次使用都需要显示的加锁和解锁, 而且提供了更高级的特性:公平锁, 定时锁, 有条件锁, 可轮询锁, 可中断锁. 可以有效避免死锁的活跃性问题.ReentrantLock实现了

Lock接口:

 
  public interface Lock {
          //阻塞直到获得锁或者中断
          void lock();

          //阻塞直到获得锁或者中断抛异常
          void lockInterruptibly() throws InterruptedException;

          //只有锁可用时才获得,否则直接返回
          boolean tryLock();

          //只有锁在指定时间内可用时才获得,否则直接返回,中断时抛异常
          boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

          void unlock();

          //返回一个绑定在这个锁上的条件
          Condition newCondition();
  }
 

Lock使用

 
        Lock lock = new ReentrantLock();
        lock.lock();
        try{
            //更新对象状态
        }finally{
            //这里注意,一定要有finally代码块去解锁
            //否则容易造成死锁等活跃性问题
            lock.unlock();
        }
 
 

ReentrantLock特性

轮询锁的和定时锁

可轮询和可定时的锁请求是通过tryLock()方法实现的,和无条件获取锁不一样. ReentrantLock可以有灵活的容错机制.死锁的很多情况是由于顺序锁引起的, 不同线程在试图获得锁的时候阻塞,并且不释放自己已经持有的锁, 最后造成死锁. tryLock()方法在试图获得锁的时候,如果该锁已经被其它线程持有,则按照设置方式立刻返回,而不是一直阻塞等下去,同时在返回后释放自己持有的锁.可以根据返回的结果进行重试或者取消,进而避免死锁的发生.

公平性

ReentrantLock构造函数中提供公平性锁和非公平锁(默认)两种选择。所谓公平锁,线程将按照他们发出请求的顺序来获取锁,不允许插队;但在非公平锁上,则允许插队:当一个线程发生获取锁的请求的时刻,如果这个锁是可用的,那这个线程将跳过所在队列里等待线程并获得锁。我们一般希望所有锁是非公平的。因为当执行加锁操作时,公平性将讲由于线程挂起和恢复线程时开销而极大的降低性能。考虑这么一种情况:A线程持有锁,B线程请求这个锁,因此B线程被挂起;A线程释放这个锁时,B线程将被唤醒,因此再次尝试获取锁;与此同时,C线程也请求获取这个锁,那么C线程很可能在B线程被完全唤醒之前获得、使用以及释放这个锁。这是种双赢的局面,B获取锁的时刻(B被唤醒后才能获取锁)并没有推迟,C更早地获取了锁,并且吞吐量也获得了提高。在大多数情况下,非公平锁的性能要高于公平锁的性能。

可中断获锁获取操作

lockInterruptibly方法能够在获取锁的同时保持对中断的响应,因此无需创建其它类型的不可中断阻塞操作。
 

读写锁ReadWriteLock

​ReentrantLock是一种标准的互斥锁,每次最多只有一个线程能持有锁。读写锁不一样,暴露了两个Lock对象,其中一个用于读操作,而另外一个用于写操作。

  1.  
    public interface ReadWriteLock {
        /**
         * Returns the lock used for reading.
         *
         * @return the lock used for reading.
         */
        Lock readLock();
    
        /**
         * Returns the lock used for writing.
         *
         * @return the lock used for writing.
         */
        Lock writeLock();
    }
     
  • 释放优先
  • 读线程插队
  • 重入性
  • 降级
  • 升级
ReentrantReadWriteLock实现了ReadWriteLock接口,构造器提供了公平锁和非公平锁两种创建方式。读写锁适用于读多写少的情况,可以实现更好的并发性。
 
示例
 
public class ReadWriteMap<K, V> {
    private Map<K, V> map;
    private final ReadWriteLock lock = new ReentrantReadWriteLock();

    private final Lock readLock = lock.readLock();
    private final Lock writeLock = lock.writeLock();

    public ReadWriteMap(Map<K, V> map) {
        this.map = map;
    }

    public V get(K key) {
        readLock.lock();
        try {
            return map.get(key);
        } finally {
            readLock.unlock();
        }
    }

    public void put(K key, V value) {
        writeLock.lock();
        try {
            map.put(key, value);
        } finally {
            writeLock.unlock();
        }
    }
}

ReentrantLock和读写锁的更多相关文章

  1. 多线程并发编程之显示锁ReentrantLock和读写锁

    在Java5.0之前,只有synchronized(内置锁)和volatile. Java5.0后引入了显示锁ReentrantLock. ReentrantLock概况 ReentrantLock是 ...

  2. 201709020工作日记--synchronized、ReentrantLock、读写锁

    1.reentrantLock java.util.concurrent.lock 中的Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 Java 类,而不是作为语言的特性来实现.这就为Lock ...

  3. 实现reentrantlock和读写锁

    1 可以手动实现一个类似reentrantlock的工具,首先要维护一个state的标志,代表当前是否有线程已经使用资源.线程lock的时候, 会用cas给state加1,其他线程检测状态.另外需要维 ...

  4. 架构师养成记--14.重入锁ReentrantLock 和 读写锁 ReentrantReadWriteLock

    ReentrantLock 有嗅探锁定和多路分支等功能,其实就是synchronized,wait,notify的升级. this锁定当前对象不方便,于是就有了用new Object()来作为锁的解决 ...

  5. 【漫画】读写锁ReadWriteLock还是不够快?再试试StampedLock!

    本文来源于公众号[胖滚猪学编程] 转载请注明出处! 在互斥锁ReentrantLock不好用?试试读写锁ReadWriteLock一文中,我们对比了互斥锁ReentrantLock和读写锁ReadWr ...

  6. Java并发-显式锁篇【可重入锁+读写锁】

    作者:汤圆 个人博客:javalover.cc 前言 在前面并发的开篇,我们介绍过内置锁synchronized: 这节我们再介绍下显式锁Lock 显式锁包括:可重入锁ReentrantLock.读写 ...

  7. 【漫画】互斥锁ReentrantLock不好用?试试读写锁ReadWriteLock

    ReentrantLock完美实现了互斥,完美解决了并发问题.但是却意外发现它对于读多写少的场景效率实在不行.此时ReentrantReadWriteLock来救场了!一种适用于读多写少场景的锁,可以 ...

  8. 深刨显式锁ReentrantLock原理及其与内置锁的区别,以及读写锁ReentrantReadWriteLock使用场景

    13.显示锁 在Java5.0之前,在协调对共享对象的访问时可以使用的机制只有synchronized和volatile.Java5.0增加了一种新的机制:ReentrantLock.与之前提到过的机 ...

  9. 【java并发编程】ReentrantLock 可重入读写锁

    目录 一.ReentrantLock可重入锁 二.ReentrantReadWriteLock读写锁 三.读锁之间不互斥 欢迎关注我的博客,更多精品知识合集 一.ReentrantLock可重入锁 可 ...

随机推荐

  1. 多重影分身——C#中多线程的使用一(基础)

    首先明确几个概念: 什么是进程? 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源. 而一个进程又是由多个线程所组成的. 一个程序通常只有一个进程(不包括exe ...

  2. Day6_正则表达式

    用作匹配数据的方法: print(re.findall('\w','yangshuai 123 asd \n \t')) #w:匹配字母数字下划线 print(re.findall('\W','yan ...

  3. win7 64位专业版下的x64编译问题

    在Django的开发过程中,碰到一个问题,就是所有本地库的位数必须是相同的,于是某些库需要重新编译一下,工作环境,不能用盗版程序,VC++ 2008\2010 Express版本身都不支持X64的编译 ...

  4. Socket.io文字直播聊天室的简单代码

    直接上代码吧,被注释掉的主要是调试代码,和技术选型的测试代码 var app = require('express')(); var server = require('http').Server(a ...

  5. EF Code First中的主外键约定和一对一、一对多关系的实现

    对于主外键约定的理解,其实是学习实体间一对一和一对多关系的基础. 1.1 主键(Key)约定 主键的默认约定是:只要字段名为--实体名(类名)+"id"(不区分大小写),这就算是默 ...

  6. C++ 利用流来进行string和其他类的转换

    通过这种方法可以实现任意转换,需要头文件 #include<string> #include<sstream> 期中sstream提供了我们的主角string流,下面给出int ...

  7. 智能指针auto_ptr & shared_ptr

    转载:智能指针auto_ptr 很多人听说过标准auto_ptr智能指针机制,但并不是每个人都天天使用它.这真是个遗憾,因为auto_ptr优雅地解决了C++设计和编码中常见的问题,正确地使用它可以生 ...

  8. spark SQL随笔

    sparkSQL 1.主要的数据结构 DataFreames 2.开始使用:SQLContext 创建步骤: Val  sc:sparkContext Val  sqlContext=new org. ...

  9. httpClient连接超时设置

    注: 每个HttpClinet对象设置都不一样 这里已3.x和4.x为例说明 1)3.X版本 创建连接 HttpClient httpClient=new DefaultHttpClient(); 这 ...

  10. Nginx+uwsgi部署django

    0. 登录远程服务器并准备 ssh 用户@IP -p 端口 回车后,要求输入服务器密码,再输入密码 更新软件源 sudo apt-get update sudo apt-get upgrade 1. ...