Java Lock ReentrantLock ReentrantReadWriteLock
Lock与Synchronized的区别:
1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;
2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;
3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
5)Lock可以提高多个线程进行读操作的效率。
在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。
ReentrantLock:
- import java.util.*;
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantLock;
- public class Main {
- public static void main(String[] args) {
- final Test test = new Test();
- new Thread(){
- public void run() {
- test.insert(Thread.currentThread());
- };
- }.start();
- new Thread(){
- public void run() {
- test.insert(Thread.currentThread());
- };
- }.start();
- }
- }
- class Test {
- private ArrayList<Integer> arrayList = new ArrayList<Integer>();
- private Lock lock = new ReentrantLock(); //注意这个地方
- public void insert(Thread thread) {
- lock.lock();
- try {
- System.out.println(thread.getName()+"得到了锁");
- for(int i=0;i<5;i++) {
- arrayList.add(i);
- }
- } catch (Exception e) {
- // TODO: handle exception
- }finally {
- System.out.println(thread.getName()+"释放了锁");
- lock.unlock();
- }
- }
- }
- Thread-0得到了锁
- Thread-0释放了锁
- Thread-1得到了锁
- Thread-1释放了锁
tryLock的使用:
tryLock()方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false,也就说这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待。
tryLock(long time, TimeUnit unit)方法和tryLock()方法是类似的,只不过区别在于这个方法在拿不到锁时会等待一定的时间,在时间期限之内如果还拿不到锁,就返回false。如果如果一开始拿到锁或者在等待期间内拿到了锁,则返回true。
- import java.util.*;
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantLock;
- public class Main {
- public static void main(String[] args) {
- final Test test = new Test();
- new Thread(){
- public void run() {
- test.insert(Thread.currentThread());
- };
- }.start();
- new Thread(){
- public void run() {
- test.insert(Thread.currentThread());
- };
- }.start();
- }
- }
- class Test {
- private ArrayList<Integer> arrayList = new ArrayList<Integer>();
- private Lock lock = new ReentrantLock(); //注意这个地方
- public void insert(Thread thread) {
- if(lock.tryLock()) {
- try {
- System.out.println(thread.getName()+"得到了锁");
- for(int i=0;i<5;i++) {
- arrayList.add(i);
- }
- } catch (Exception e) {
- // TODO: handle exception
- }finally {
- System.out.println(thread.getName()+"释放了锁");
- lock.unlock();
- }
- } else {
- System.out.println(thread.getName()+"获取锁失败");
- }
- }
- }
- Thread-0得到了锁
- Thread-0释放了锁
- Thread-1获取锁失败
lockInterruptibly()响应中断方法:
lockInterruptibly()方法比较特殊,当通过这个方法去获取锁时,如果线程正在等待获取锁,则这个线程能够响应中断,即中断线程的等待状态。也就使说,当两个线程同时通过lock.lockInterruptibly()想获取某个锁时,假若此时线程A获取到了锁,而线程B只有在等待,那么对线程B调用threadB.interrupt()方法能够中断线程B的等待过程。
由于lockInterruptibly()的声明中抛出了异常,所以lock.lockInterruptibly()必须放在try块中或者在调用lockInterruptibly()的方法外声明抛出InterruptedException。
注意,当一个线程获取了锁之后,是不会被interrupt()方法中断的。因为本身在前面的文章中讲过单独调用interrupt()方法不能中断正在运行过程中的线程,只能中断阻塞过程中的线程。
因此当通过lockInterruptibly()方法获取某个锁时,如果不能获取到,只有进行等待的情况下,是可以响应中断的。
而用synchronized修饰的话,当一个线程处于等待某个锁的状态,是无法被中断的,只有一直等待下去。
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantLock;
- public class Main {
- public static void main(String[] args) {
- Test test = new Test();
- MyThread thread1 = new MyThread(test);
- MyThread thread2 = new MyThread(test);
- thread1.start();
- thread2.start();
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- thread2.interrupt();
- }
- }
- class Test {
- private Lock lock = new ReentrantLock();
- public void insert(Thread thread) throws InterruptedException{
- lock.lockInterruptibly(); //注意,如果需要正确中断等待锁的线程,必须将获取锁放在外面,然后将InterruptedException抛出
- try {
- System.out.println(thread.getName()+"得到了锁");
- long startTime = System.currentTimeMillis();
- for( ; ;) {
- if(System.currentTimeMillis() - startTime >= Integer.MAX_VALUE)
- break;
- //插入数据
- }
- }
- finally {
- System.out.println(Thread.currentThread().getName()+"执行finally");
- lock.unlock();
- System.out.println(thread.getName()+"释放了锁");
- }
- }
- }
- class MyThread extends Thread {
- private Test test = null;
- public MyThread(Test test) {
- this.test = test;
- }
- @Override
- public void run() {
- try {
- test.insert(Thread.currentThread());
- } catch (InterruptedException e) {
- System.out.println(Thread.currentThread().getName()+"被中断");
- }
- }
- }
- Thread-0得到了锁
- Thread-1被中断
读写锁:ReentrantReadWriteLock()
使用syschronized读
- import java.util.concurrent.locks.ReentrantReadWriteLock;
- public class Main {
- public static void main(String[] args) {
- final Test test = new Test();
- new Thread(){
- public void run() {
- test.get(Thread.currentThread());
- };
- }.start();
- new Thread(){
- public void run() {
- test.get(Thread.currentThread());
- };
- }.start();
- }
- }
- class Test {
- private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
- public synchronized void get(Thread thread) {
- long start = System.currentTimeMillis();
- while(System.currentTimeMillis() - start <= 1) {
- System.out.println(thread.getName()+"正在进行读操作");
- }
- System.out.println(thread.getName()+"读操作完毕");
- }
- }
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0读操作完毕
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1读操作完毕
使用Lock的读锁
- import java.util.concurrent.locks.ReentrantReadWriteLock;
- public class Main {
- public static void main(String[] args) {
- final Test test = new Test();
- new Thread(){
- public void run() {
- test.get(Thread.currentThread());
- };
- }.start();
- new Thread(){
- public void run() {
- test.get(Thread.currentThread());
- };
- }.start();
- }
- }
- class Test {
- private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
- public void get(Thread thread) {
- rwl.readLock().lock();
- try {
- long start = System.currentTimeMillis();
- while(System.currentTimeMillis() - start <= 1) {
- System.out.println(thread.getName()+"正在进行读操作");
- }
- System.out.println(thread.getName()+"读操作完毕");
- } finally {
- rwl.readLock().unlock();
- }
- }
- }
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-1正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0正在进行读操作
- Thread-0读操作完毕
- Thread-1正在进行读操作
- Thread-1读操作完毕
读写锁表示两个锁,一个是读操作相关的锁,称为共享锁;另一个是写操作相关的锁,称为排他锁。我把这两个操作理解为三句话:
1、读和读之间不互斥,因为读操作不会有线程安全问题
2、写和写之间互斥,避免一个写操作影响另外一个写操作,引发线程安全问题
3、读和写之间互斥,避免读操作的时候写操作修改了内容,引发线程安全问题
总结起来就是,多个Thread可以同时进行读取操作,但是同一时刻只允许一个Thread进行写入操作。
注意的是,如果有一个线程已经占用了读锁,则此时其他线程如果要申请写锁,则申请写锁的线程会一直等待释放读锁。
如果有一个线程已经占用了写锁,则此时其他线程如果申请写锁或者读锁,则申请的线程会一直等待释放写锁。
加读锁的目的是防止写锁,加写锁的目的是为了防止读锁和写锁,读锁本身并不防止读锁。
ReentrantReadWriteLock代码分析:http://blog.csdn.net/prestigeding/article/details/53286756
http://www.cnblogs.com/dolphin0520/p/3923167.html
http://blog.csdn.net/aitangyong/article/details/38315885
http://www.cnblogs.com/benshan/p/3551987.html
http://ifeve.com/java_lock_see/
http://agapple.iteye.com/blog/970055
https://www.cnblogs.com/szlbm/p/5588512.html
Java Lock ReentrantLock ReentrantReadWriteLock的更多相关文章
- 高并发第十一弹:J.U.C -AQS(AbstractQueuedSynchronizer) 组件:Lock,ReentrantLock,ReentrantReadWriteLock,StampedLock
既然说到J.U.C 的AQS(AbstractQueuedSynchronizer) 不说 Lock 是不可能的.不过实话来说,一般 JKD8 以后我一般都不用Lock了.毕竟sychronize ...
- Java Lock Example – ReentrantLock(java锁的例子)
Welcome to Java Lock example tutorial. Usually when working with multi-threaded environment, we use ...
- 转载:Java Lock机制解读
Java Lock机制解读 欢迎转载: https://blog.csdn.net/chengyuqiang/article/details/79181229 1.synchronized synch ...
- 深入分析 Java Lock 同步锁
前言 Java 的锁实现,有 Synchronized 和 Lock.上一篇文章深入分析了 Synchronized 的实现原理:由Java 15废弃偏向锁,谈谈Java Synchronized 的 ...
- Java之ReentrantLock公平锁和非公平锁
在Java的ReentrantLock构造函数中提供了两种锁:创建公平锁和非公平锁(默认).代码如下: public ReentrantLock() { sync = new NonfairSync( ...
- Java并发指南10:Java 读写锁 ReentrantReadWriteLock 源码分析
Java 读写锁 ReentrantReadWriteLock 源码分析 转自:https://www.javadoop.com/post/reentrant-read-write-lock#toc5 ...
- java 并发——ReentrantLock
java 并发--ReentrantLock 简介 public class ReentrantLock implements Lock, java.io.Serializable { // 继承了 ...
- Java线程--ReentrantLock使用
原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11871593.html Java线程--ReentrantLock使用, 互斥锁: Reent ...
- Java Concurrency - ReadWriteLock & ReentrantReadWriteLock
锁所提供的最重要的改进之一就是 ReadWriteLock 接口和它的实现类 ReentrantReadWriteLock.这个类提供两把锁,一把用于读操作和一把用于写操作.同一时间可以有多个线程执行 ...
随机推荐
- Self Service Password (SSP)
安装SSP, 依赖包包括php5, php5-ldap, php5-mcrypt 启用mcrypt功能: sudo php5enmod mcrypt 第一部分: Apache 安装Apache, 并且 ...
- 【转】Java跨平台原理
原文地址:http://www.cnblogs.com/gw811/archive/2012/09/09/2677386.html 1.是么是平台 Java是可以跨平台的编程语言,那我们首先得知道什么 ...
- Javascript 笔记与总结(2-9)获取运行时的 style 对象
获取内存中(正在渲染)的 style 的值(非内联 style,obj.style 只能获得内联 style 的值),可以用 obj.currentStyle(低版本 IE 和 Opera 支持)和 ...
- win7系统安装FAQ
安装失败: 直接重启后进入原系统 蓝屏 提示失败 开机F1进入BIOS-〉config-〉Serial ATA-〉将硬盘模式从AHCI改为Compatibility.这项很重要的.可以解决以上问题:
- Bootstrap学习笔记1
Bootstrap在线手册 http://v3.bootcss.com,这里有详细的说明.参考.示例. Bootstrap为许多前端常用的功能都做了封装.预定义,可以直接使用. Bootstrap支持 ...
- 微博app中常用正则表达式
/* weibo.app 里面的正则,有兴趣的可以参考下: HTTP链接 (例如 http://www.weibo.com ): ([hH]ttp[s]{0,1})://[a-zA-Z0-9\.\-] ...
- Android 一键直接查看Sqlite数据库数据
转自:http://www.cnblogs.com/trinea/archive/2012/11/16/2773656.html 本文主要介绍Android开发中如何一键直接查看sqlite数据库中的 ...
- 详解linux系统的启动过程及系统初始化
一.linux系统的启动流程 关于linux系统的启动流程我们可以按步进行划分为如下: POST加电自检 -->BIOS(Boot Sequence)-->加载对应引导上的MBR(boot ...
- Mschat控件示例升级错误处理方法
将具有 3.5 版图表控件的 ASP.NET 3.5 网站升级到 ASP.NET 4 需要更改 web.config 和注册指令 将具有 3.5 版图表控件的 ASP.NET 3.5 网站升级到 AS ...
- Qt 无边框窗体改变大小 完美实现(全部自己实现)
近期,做项目用到无边框窗体,令人蛋疼的是无边框窗体大小的改变要像右边框那样,上下左右四周,而且要流畅. 网上也找了些代码,发现居然还要连接到windows事件,这显然不合常理,后来自己新建了demo, ...