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 ...
随机推荐
- springboot(12)Redis作为SpringBoot项目数据缓存
简介: 在项目中设计数据访问的时候往往都是采用直接访问数据库,采用数据库连接池来实现,但是如果我们的项目访问量过大或者访问过于频繁,将会对我们的数据库带来很大的压力.为了解决这个问题从而redis数据 ...
- JVM系列之:String.intern和stringTable
目录 简介 intern简介 intern和字符串字面量常量 分析intern返回的String对象 分析实际的问题 G1中的去重功能 总结 简介 StringTable是什么?它和String.in ...
- PHP timezone_version_get() 函数
------------恢复内容开始------------ 实例 返回时区数据库的版本: <?phpecho timezone_version_get();?> 运行实例 » 定义和用法 ...
- Hadoop学习之常用输入输出格式总结
目的 总结一下常用的输入输出格式. 输入格式 Hadoop可以处理很多不同种类的输入格式,从一般的文本文件到数据库. 开局一张UML类图,涵盖常用InputFormat类的继承关系与各自的重要方法(已 ...
- 开源后端数据校验插件Validate.Net,类似Validate.js
介绍 Validate.Net将Validate.js移植到.Net平台,可以更方便.更快捷的校验实体内属性值是否合法.内置多种常规数据校验规则(校验必填.校验字符串长度区间.校验最大最小值.校验值区 ...
- 【oracle】-集合运算:UNION,UNION ALL...
在Oracle中提供了三种类型的集合操作: 并(UNION).交(INTERSECT).差(MINUS) UNION:求并,重复记录只显示一次. UNION ALL:求并集,显示所有记录信息. INT ...
- 解决IIS发布时CS0016未能写入输出文件错误
今天遇到一个将asp.net项目部署到IIS后访问的时候报的一个错误: 在网上查询了相关资料后,解决方法如下: 找到C:\Windows\下的temp文件,右键属性>安全>编辑,给其中II ...
- fastjson JSON.toJavaObject() 实体类首字母大写属性无法解析问题
fastjson JSON.toJavaObject() 实体类首字母大写属性无法解析问题
- DataGrip,一款数据库客户端工具,IDEA的兄弟是真香!
DataGrip 是一款数据库管理客户端工具,方便的连接到数据库服务器,执行sql语句.创建表.创建索引以及导出数据等. DataGrip 支持几乎所有主流的关系数据库产品,如 DB2.Derby.H ...
- 你不是说你会Aop吗?
一大早,小王就急匆匆的跑过来找我,说:周哥,那个记录日志的功能我想请教一下. 因为公司某个项目要跟别的平台做对接,我们这边需要给他们提供一套接口.昨天,我就将记录接口日志的工作安排给了小王. 下面是我 ...