代码在后面

读锁 = 共享锁

读锁写锁,公用一个Sync AQS state。

写锁是排他的,看到有人获取锁,他不会去获取,他获取了锁,别人也不会进来获取锁。

写锁的获取跟ReentarntLock一样,每次加1,是一个独占锁,只要有人获取了锁,自己就去排队,排队时候节点是EXCLUSIVE的节点,入队方法acquireQueuedReentarntLock一样,会设置OwnerThread。

读锁先获取锁,后面有读锁进来,多个读线程共存时候,第一个读线程设置firstReader,其余读线程设置threadLocals属性,然后获取锁,读锁每次增加65536,

写锁再进来,就去排队。

读锁再又进来,读锁还是去排队,

读锁不会设置OwnerThread,只是会state增加65536,写锁会忽略大于65536的部分。

state!=0,state去掉前16位=0,说明有读锁进去,写锁不进去。

State高位存储读锁获取次数,低位存储写锁获取次数。

设置threadLocals属性的读线程unlock时候清除threadLocalMap的标记,设置firstReader的读线程unlock时候设置firstReader=null,并且state减65536,

//读锁进来,首先判断state后16位,有写锁就去排队,没有写锁就设置firstReader或者firstReaderHoldCount++或者当前线程的threadLocals并且state增加65536
//写锁进来时候,首先判断state,有读锁写锁就去排队,

1.读锁进来,不看owenerThread,看的是state,去掉前面16位=0,说明没有写线程获取锁,就设置firstReader或者threadLocalMap,state增加65536。state去掉前面16位!=0说明有写线程获得了锁,就去排队。如果队列第一个是写线程,就去排队。 如果后面还有读线程进来,照样。

2.写锁进来,state!=0,state去掉前面16位=0,说明state已经加了几个65536了,说明有线程在读,写锁要去排队。state=0说明没有写线程获取锁,没有读线程在读,就去获取锁。state!=0,state去掉前面16位!=0,说明state有写线程获取锁,就去排队。

读锁每次加65536,不设置owenerThread。写锁每次加1,设置owenerThread。

读:去掉前面16!=0就去排队,队列空设置firstReader或者threadLocalMap,第一个节点是写线程排队,第一个节点是读线程设置firstReader或者threadLocalMap。

写:state!=0,去掉前面16位=0去排队,state=0获取锁。

if (exclusiveCount(c) != 0 /*去掉前面16位,*/ && getExclusiveOwnerThread() != current)

获取读锁时候,去掉前面16位!=0,OwnerThread() = current,说明里面有写锁了,并且是自己。说明一个线程先获取写锁在获取读锁,那么这个线程占据了owenerThread和firstReader或者threadLocalMap。

public class ReadWriteLockTest<E> {
private final Map<String, String> map = new TreeMap<>();
private final ReentrantReadWriteLock1 lock = new ReentrantReadWriteLock1();
//写的时候,不能读不能写。 读的时候,不能写可以读。 //读线程获取锁,其他读线程可以获取锁,写线程不能获取锁
//写线程获取锁,读线程写线程不能获取锁
private final ReentrantReadWriteLock1.ReadLock readLock = lock.readLock();
private final ReentrantReadWriteLock1.WriteLock writeLock = lock.writeLock(); public ReadWriteLockTest() {
} public String write(String key, String value) throws InterruptedException {
writeLock.lock();//写锁是排他的,看到有人获取锁,他不会去获取,他获取了锁别人也不会进来获取锁。
readLock.lock();
// writeLock.lockInterruptibly();
// writeLock.tryLock();
try {
return map.put(key, value);
} finally {
writeLock.unlock();//写锁释放,就唤醒AQS
}
} public String read(String key) throws InterruptedException {
readLock.lock();//获取的是共享锁
// writeLock.lock();
// readLock.lockInterruptibly();
// readLock.tryLock();
try {
return map.get(key);
} finally {
readLock.unlock();//读锁全部释放完了,才会去唤醒AQS
}
} private static ReadWriteLockTest<Integer> tt = new ReadWriteLockTest<Integer>(); public static void main(String[] args) {
new Thread(() -> {
int i = ;
while (true) {
Write w = new Write("写--" + (i++));
w.start();
}
}).start(); new Thread(() -> {
int j = ;
while (true) {
Read s1 = new Read("读--" + (j++));
s1.start();
// Read s2 = new Read("读--" + (j++));
// s2.start();
// Read s3 = new Read("读--" + (j++));
// s3.start();
// s1.interrupt();
// s2.interrupt();
// s3.interrupt();
}
}).start();
}
static int i =;static int j = ;
static class Write extends Thread {
Write(String name) {
super(name);
}
@Override
public void run() {
try {
tt.write((i++)+"",(j++)+"");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} static class Read extends Thread {
Read(String name) {
super(name);
}
@Override
public void run() {
try {
tt.read((i--)+"");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

最新文章

  1. GOF23设计模式之单例模式
  2. p/invoke碎片,对结构体的处理
  3. jQuery源码分析系列(40): 动画设计
  4. HDU 1166 敌兵布阵(线段树单点更新)
  5. redis的基本使用
  6. mac:ssh登陆总是需要输入钥匙串密码解决
  7. JSP/Servlet基础语法
  8. Web---HTTP请求、重定向、转发和数据压缩
  9. hook研究结果备忘
  10. 利用GitLab webhook来实现触发Jenkins自动操作
  11. 2018-2019-2-20175225 实验一 《Java开发环境的熟悉》实验报告
  12. React Native(十三)&mdash;&mdash;ios键盘挡住textInput
  13. font-awesome图标
  14. CSS ... 文本溢出用省略号代替
  15. uboot的FIT功能
  16. Excel函数sumproduct应用案例-多条件求和
  17. ODATA4 及实现
  18. mysql--事务demo1----
  19. git——解决“fatal: Authentication failed for &#39;https://github.com/balabala”
  20. iOS开发遇到的坑之五--解决工程已存在plist表,数据却不能存入的问题

热门文章

  1. 我为啥不想用Python
  2. SpringMVC-拦截器做一个登录认证的小Demo
  3. Object.assign的使用
  4. 算法-memcopy与memmove的区别
  5. MySQL 重要参数 innodb_flush_log_at_trx_commit 和 sync_binlog
  6. Idea中Spring整合MyBatis框架中配置文件中对象注入问题解决方案
  7. Spring Boot Admin 详解(Spring Boot 2.0,基于 Eureka 的实现)
  8. Unity 渲染教程(一):矩阵
  9. 在eclipse中安装使用lombok插件
  10. 使用SpringBoot编写Restful风格接口