独占锁:是指锁一次只能被一个线程持有,ReentrantLock和Synchronized都是独占锁。

共享锁:是指锁可以被多个线程持有。

对于ReentrantReadWriteLock,其读锁是共享锁,写锁是独占锁。

代码示例:如果不设置锁,下面这块代码执行后就会造成一段写操作在完成之前被多个其他操作打断。

 package com.freud.algorithm.other;

 import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
* 资源类
*/
class MyCache { private volatile Map<String, Object> map = new HashMap<>();
// private Lock lock = new ReentrantLock();
public void put(String key, Object value) { System.out.println(Thread.currentThread().getName() + "\t 正在写入:" + key);
// 暂停一会儿线程
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
map.put(key, value);
System.out.println(Thread.currentThread().getName() + "\t 写入完成");
} public void get(String key) { System.out.println(Thread.currentThread().getName() + "\t 正在读取:");
// 暂停一会儿线程
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
Object value = map.get(key);
System.out.println(Thread.currentThread().getName() + "\t 读取完成:" + value);
}
} /**
* 多个线程同时读一个资源类没有任何问题,所以为了满足并发量,读取共享资源应该可以同时进行
* 但是,如果有一个线程想去写共享资源,就不应该再有其他线程可以对这个资源进行读或者写
* 小总结:
* 读-读能共存
* 读-写不能共存
* 写-写不能共存
*/
public class ReadWriteLockDemo { public static void main(String[] args) { MyCache myCache = new MyCache(); for (int i = 0; i < 5; i++) {
final int tempInt = i;
new Thread(() -> {
myCache.put(tempInt + "", tempInt + "");
}, String.valueOf(i)).start();
} for (int i = 0; i < 5; i++) {
final int tempInt = i;
new Thread(() -> {
myCache.get(tempInt + "");
}, String.valueOf(i)).start();
}
}
}

打印:

 "C:\Program Files\Java\jdk1.8.0_191\bin\java" "-javaagent:E:\Jetbrains\IntellijIDEA\IntelliJ IDEA 2017.2.6\lib\idea_rt.jar=12592:E:\Jetbrains\IntellijIDEA\IntelliJ IDEA 2017.2.6\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_191\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\rt.jar;E:\practise\algorithm\out\production\algorithm" com.freud.algorithm.other.ReadWriteLockDemo
1 正在写入:1
0 正在写入:0
2 正在写入:2
3 正在写入:3
4 正在写入:4
0 正在读取:
1 正在读取:
2 正在读取:
3 正在读取:
4 正在读取:
1 写入完成
1 读取完成:1
0 读取完成:0
0 写入完成
2 写入完成
4 写入完成
3 写入完成
4 读取完成:null
3 读取完成:null
2 读取完成:2 Process finished with exit code 0

为了解决这个问题,使得写操作保证原子性不被其他线程打断,加了ReadWriteLock。

 package com.freud.algorithm.other;

 import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; /**
* 资源类
*/
class MyCache { private volatile Map<String, Object> map = new HashMap<>();
// 传统的Lock不足以满足需求
// private Lock lock = new ReentrantLock();
/**
* JUC提供了ReentrantReadWriteLock
*/
private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); /**
* put方法
* @param key
* @param value
*/
public void put(String key, Object value) { rwLock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "\t 正在写入:" + key);
// 暂停一会儿线程
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
map.put(key, value);
System.out.println(Thread.currentThread().getName() + "\t 写入完成");
} catch (Exception e) {
e.printStackTrace();
} finally {
rwLock.writeLock().unlock();
}
} /**
* get方法
* @param key
*/
public void get(String key) { rwLock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "\t 正在读取:");
// 暂停一会儿线程
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
Object value = map.get(key);
System.out.println(Thread.currentThread().getName() + "\t 读取完成:" + value);
} catch (Exception e) {
e.printStackTrace();
} finally {
rwLock.readLock().unlock();
}
}
} /**
* 多个线程同时读一个资源类没有任何问题,所以为了满足并发量,读取共享资源应该可以同时进行
* 但是,如果有一个线程想去写共享资源,就不应该再有其他线程可以对这个资源进行读或者写
* 小总结:
* 读-读能共存
* 读-写不能共存
* 写-写不能共存
*/
public class ReadWriteLockDemo { public static void main(String[] args) { MyCache myCache = new MyCache(); for (int i = 0; i < 5; i++) {
final int tempInt = i;
new Thread(() -> {
myCache.put(tempInt + "", tempInt + "");
}, String.valueOf(i)).start();
} for (int i = 0; i < 5; i++) {
final int tempInt = i;
new Thread(() -> {
myCache.get(tempInt + "");
}, String.valueOf(i)).start();
}
}
}

打印:

"C:\Program Files\Java\jdk1.8.0_191\bin\java" "-javaagent:E:\Jetbrains\IntellijIDEA\IntelliJ IDEA 2017.2.6\lib\idea_rt.jar=18187:E:\Jetbrains\IntellijIDEA\IntelliJ IDEA 2017.2.6\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_191\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\rt.jar;E:\practise\algorithm\out\production\algorithm" com.freud.algorithm.other.ReadWriteLockDemo
0 正在写入:0
0 写入完成
1 正在写入:1
1 写入完成
2 正在写入:2
2 写入完成
3 正在写入:3
3 写入完成
4 正在写入:4
4 写入完成
1 正在读取:
0 正在读取:
3 正在读取:
4 正在读取:
2 正在读取:
2 读取完成:2
4 读取完成:4
3 读取完成:3
0 读取完成:0
1 读取完成:1 Process finished with exit code 0

Java锁_读写锁的更多相关文章

  1. 二、多线程基础-乐观锁_悲观锁_重入锁_读写锁_CAS无锁机制_自旋锁

    1.10乐观锁_悲观锁_重入锁_读写锁_CAS无锁机制_自旋锁1)乐观锁:就像它的名字一样,对于并发间操作产生的线程安全问题持乐观状态,乐观锁认为竞争不总是会发生,因此它不需要持有锁,将 比较-设置 ...

  2. 多线程编程之Apue3rd_Chapter11之互斥锁_读写锁_自旋锁

    学习了apue3rd的第11章,主要讲的是多线程编程.因为线程共享进程的资源比如堆和全局变量,多线程编程最重要的是,使用各种锁进行线程同步. 线程编程首先要学习的三个函数如下: #include &l ...

  3. JAVA锁机制-可重入锁,可中断锁,公平锁,读写锁,自旋锁,

    如果需要查看具体的synchronized和lock的实现原理,请参考:解决多线程安全问题-无非两个方法synchronized和lock 具体原理(百度) 在并发编程中,经常遇到多个线程访问同一个 ...

  4. Java中的锁-悲观锁、乐观锁,公平锁、非公平锁,互斥锁、读写锁

    总览图 如果文中内容有错误,欢迎指出,谢谢. 悲观锁.乐观锁 悲观锁.乐观锁使用场景是针对数据库操作来说的,是一种锁机制. 悲观锁(Pessimistic Lock):顾名思义,就是很悲观,每次去拿数 ...

  5. golang互斥锁和读写锁

    一.互斥锁 互斥锁是传统的并发程序对共享资源进行访问控制的主要手段.它由标准库代码包sync中的Mutex结构体类型代表.sync.Mutex类型(确切地说,是*sync.Mutex类型)只有两个公开 ...

  6. 从自旋锁、睡眠锁、读写锁到 Linux RCU 机制讲解

    ​    同步自我的 csdn 博客 6.S081 从自旋锁.睡眠锁.读写锁到 Linux RCU 机制讲解_我说我谁呢 --CSDN博客 总结一下 O/S 课程里面和锁相关的内容. 本文是 6.S0 ...

  7. Go语言基础之13--线程安全及互斥锁和读写锁

    一.线程安全介绍 1.1 现实例子 A. 多个goroutine同时操作一个资源,这个资源又叫临界区 B. 现实生活中的十字路口,通过红路灯实现线程安全 C. 火车上的厕所(进去之后先加锁,在上厕所, ...

  8. 多线程编程_读写锁ReadWriteLock

    Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象. 读写锁:分为读 ...

  9. PHP程序中的文件锁、互斥锁、读写锁使用技巧解析

    文件锁全名叫 advisory file lock, 书中有提及. 这类锁比较常见,例如 mysql, php-fpm 启动之后都会有一个pid文件记录了进程id,这个文件就是文件锁. 这个锁可以防止 ...

随机推荐

  1. CSDN首页

    打开CSDN首页,大部分的内容都是——AI,大数据,Python,很少谈及C#,谈到了也是拿C#做反面对比.博客园的首页没有这种恶意诋毁的言论,什么都有,.net的文章也很多,你发你的大数据和AI,我 ...

  2. Tornado之异步非阻塞

    同步模式:同步模式下,只有处理完前一个任务下一个才会执行 class MainHandler(tornado.web.RequestHandler): def get(self): time.slee ...

  3. java语言基础(三)_数组

    数组 是引用类型 1. 容器:是将多个数据存储到一起,每个数据称为该容器的元素. 2. 数组概念:数组就是存储数据长度固定的容器,保证多个数据的数据类型要一致. 特点: 数组是一种引用数据类型 数组当 ...

  4. 【板子】数论基础(持续更新ing...)

    #include<cstdio> #include<iostream> #include<cstring> #include<cmath> #inclu ...

  5. java 和 c++ 的三目运算符的区别

    转载请注明出处:http://www.cnblogs.com/liangyongrui/p/6348001.html 以前很少用java,就知道java和c++差不多. 今天就踩了一个坑. 不吐糟,直 ...

  6. efcore 跨表查询,实现一个接口内查询两个不同数据库里各自的表数据

    最近有efcore跨库查询的需求,研究了下colder框架里文档的分库实现,发现并不能完全实现一个接口下的跨库查询请求,只能满足一个业务层构造指定的唯一一个数据库访问接口. 先说下文档是怎么实现的 D ...

  7. mysql逗号分隔问题

    1.说明: 之前写了一个发先了有点问题, 用正则去匹配的会匹配多了数据,所以优化下 媒资表(asset_baseinfo)里面有地区,如下,如果一个节目包含多个地区,id存在如下 地区表(produc ...

  8. JSR 303 进行后台数据校验

    一.JSR 303 1.什么是 JSR 303? JSR 是 Java Specification Requests 的缩写,即 Java 规范提案. 存在各种各样的 JSR,简单的理解为 JSR 是 ...

  9. Hangfire实战(一)------Hangfire+SQL Server实现简单的任务调度

    Hangfire:一个开源的任务调度框架 开发环境:VS2017,SQL Server 2012,.NET Framework 4.5 项目类型:控制台应用程序 1.在vs的程序包控制台中为项目添加H ...

  10. 2.5万字长文简单总结SpringMVC请求参数接收

    这是公众号<Throwable文摘>发布的第22篇原创文章,暂时收录于专辑<架构与实战>.暂定下一篇发布的长文是<图文分析JUC同步器框架>,下一篇发布的短文是&l ...