JUC----04
1.1 读写问题
ReadWriteLockUnsafeDemo:
public class ReadWriteLockUnsafeDemo {
// TODO: 2020/7/25 模拟多线程对公共资源类的读和写操作,没有加锁,不安全
static class Cache {
private HashMap<String, Object> cache = new HashMap<>();
//写入缓存
public void put(String key, Object val) {
try {
System.out.println(Thread.currentThread().getName() + " 开始写入");
cache.put(key, val);
System.out.println(Thread.currentThread().getName() + " 写入完成");
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
//从缓存中读取数据
public void get(String key) {
try {
System.out.println(Thread.currentThread().getName() + " 开始读取");
Object obj = cache.get(key);
System.out.println(Thread.currentThread().getName() + " 读取完成 : " + obj);
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}
public static void main(String[] args) {
Cache cache = new Cache();
for (int i = 0; i < 5; ++i) {
final int tempI = i;
new Thread(() -> {
cache.put(String.valueOf(tempI), tempI);
}).start();
}
for (int i = 0; i < 5; ++i) {
final int tempI = i;
new Thread(() -> {
cache.get(String.valueOf(tempI));
}).start();
}
}
}
运行结果:
Thread-0 开始写入
Thread-1 开始写入
Thread-1 写入完成
Thread-0 写入完成
Thread-2 开始写入
Thread-2 写入完成
Thread-3 开始写入
Thread-3 写入完成
Thread-5 开始读取
Thread-5 读取完成 : 0
Thread-4 开始写入
Thread-4 写入完成
Thread-6 开始读取
Thread-6 读取完成 : 1
Thread-7 开始读取
Thread-7 读取完成 : 2
Thread-8 开始读取
Thread-9 开始读取
Thread-9 读取完成 : 4
Thread-8 读取完成 : 3
首先我们可以发现在写操作的时候线程发生的争抢。
ReadWriteLockDemo:
public class ReadWriteLockDemo {
/**
* * 读-读 : 无锁
* * 读-写 : 锁
* * 写-写 : 锁
*/
//模拟缓存被读和被写
static class Cache {
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private HashMap<String, Object> cache = new HashMap<>();
//写入缓存
public void put(String key, Object val) {
/**
* 加写锁
*/
readWriteLock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + " 开始写入");
cache.put(key, val);
System.out.println(Thread.currentThread().getName() + " 写入完成");
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.writeLock().unlock();
}
}
//从缓存中读取数据
public void get(String key) {
/**
* 加读锁
*/
readWriteLock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + " 开始读取");
Object obj = cache.get(key);
System.out.println(Thread.currentThread().getName() + " 读取完成 : " + obj);
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.readLock().unlock();
}
}
}
public static void main(String[] args) {
Cache cache = new Cache();
for (int i = 0; i < 5; ++i) {
final int tempI = i;
new Thread(() -> {
cache.put(String.valueOf(tempI), tempI);
}).start();
}
for (int i = 0; i < 5; ++i) {
final int tempI = i;
new Thread(() -> {
cache.get(String.valueOf(tempI));
}).start();
}
}
}
运行结果:
Thread-0 开始写入
Thread-0 写入完成
Thread-1 开始写入
Thread-1 写入完成
Thread-2 开始写入
Thread-2 写入完成
Thread-3 开始写入
Thread-3 写入完成
Thread-4 开始写入
Thread-4 写入完成
Thread-5 开始读取
Thread-5 读取完成 : 0
Thread-6 开始读取
Thread-6 读取完成 : 1
Thread-7 开始读取
Thread-7 读取完成 : 2
Thread-8 开始读取
Thread-8 读取完成 : 3
Thread-9 开始读取
Thread-9 读取完成 : 4
可以看到写操作保证了原子性,读操作不加锁任意读。
这里的读操作不加锁,可能有些人会说既然不加锁,那为什么这一步要获取读锁?

这里的加锁是为了和读操作分离开来,保证上面的读锁释放完后(读操作做完了)再进行读,而各个读线程之间是不加锁的。
java这部分东西都藏在源码里了,我个人认为上面的代码严格来说属于写优先算法。写写互斥,写优先。
熟悉操作系统的都知道读写问题一般分三种:
- 读优先
- 写优先
- 读写公平
JUC----04的更多相关文章
- Java多线程系列--“JUC集合”04之 ConcurrentHashMap
概要 本章是JUC系列的ConcurrentHashMap篇.内容包括:ConcurrentHashMap介绍ConcurrentHashMap原理和数据结构ConcurrentHashMap函数列表 ...
- Java多线程系列--“JUC锁”04之 公平锁(二)
概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...
- Java多线程系列--“JUC原子类”04之 AtomicReference原子类
概要 本章对AtomicReference引用类型的原子类进行介绍.内容包括:AtomicReference介绍和函数列表AtomicReference源码分析(基于JDK1.7.0_40)Atomi ...
- Java多线程系列--“JUC线程池”04之 线程池原理(三)
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--“基础篇”01之 基 ...
- java多线程系类:JUC线程池:04之线程池原理(三)(转)
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--"基础篇& ...
- java多线程系类:JUC原子类:04之AtomicReference原子类
概要 本章对AtomicReference引用类型的原子类进行介绍.内容包括:AtomicReference介绍和函数列表AtomicReference源码分析(基于JDK1.7.0_40)Atomi ...
- Java多线程系列 JUC线程池04 线程池原理解析(三)
转载 http://www.cnblogs.com/skywang12345/p/3509954.html https://blog.csdn.net/qq_22929803/article/det ...
- JUC 并发编程--04 常用的辅助类CountDownLatch , CyclicBarrier , Semaphore , 读写锁 , 阻塞队列,CompletableFuture(异步回调)
CountDownLatch 相当于一个减法计数器, 构造方法指定一个数字,比如6, 一个线程执行一次,这个数字减1, 当变为0 的时候, await()方法,才开始往下执行,, 看这个例子 Cycl ...
- Java多线程系列--“JUC锁”03之 公平锁(一)
概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...
- Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例
概要 本章介绍JUC包中的CyclicBarrier锁.内容包括:CyclicBarrier简介CyclicBarrier数据结构CyclicBarrier源码分析(基于JDK1.7.0_40)Cyc ...
随机推荐
- ls -bash: ls: command not found
ls -bash: ls: command not found原因:在设置环境变量时,编辑profile文件没有写正确,导致在命令行下 ls等命令不能够识别.解决方案: export PATH=/us ...
- 利用Python的装饰器一键开启多线程
记录一下自己写的烂代码 import time import threading def WithThread(obj): """这是一个开启线程的装饰器"&q ...
- python学习笔记1 -- 函数式编程之高阶函数 filter
filter 函数用于过滤序列,与map 和reduce函数类似,作为高阶函数,他们也是同样的使用方法,filter(参数1, 参数2),参数1是一个函数,而参数2是一个序列. filter的作用是根 ...
- PHP 标量类型与返回值类型声明
标量类型声明 默认情况下,所有的PHP文件都处于弱类型校验模式. PHP 7 增加了标量类型声明的特性,标量类型声明有两种模式: 强制模式 (默认) 严格模式 标量类型声明语法格式: declare( ...
- PHP mysqli_sqlstate() 函数
返回最后一个 MySQL 操作的 SQLSTATE 错误代码: <?php 高佣联盟 www.cgewang.com // 假定数据库用户名:root,密码:123456,数据库:RUNOOB ...
- SLAM中的逆深度参数化
参数化问题 在SLAM的建图过程中,把像素深度假设成了高斯分布.那么这么假设是否是合适的呢?这里关系到一个参数化的问题. 我们经常用一个点的世界坐标x,y,z三个量来描述它,这是一种参数化形式.我们认 ...
- python文件的执行
python文件的后缀名没有限制,但是为了后来导入模版的规范性,python代码通常以".py"作为后缀: python文件运行 一般情况都是解释器+文件名,如:python ** ...
- 同一台服务器部署三个Tomcat
工具 apache-tomcat-8.0.30 安装tomcat步骤 1. 下载apache-tomcat-8.0.30 ,下载下来的文件为apache-tomcat-8.0.30 ...
- javascript 字符串对象
数组转换字符串 tostring() 将数组转换成字符串 join(分隔符)将数组转换成字符串 基本包装类型 基本包装类型 就是把简单数据类型 包装成繁杂数据类型 ...
- angular.js 本地数据存储LocalStorage
定义工厂模式 factory 本地存储数据服务 app.factory('locals', ['$window', function ($window) { return { //存储单个属性 se ...