实现reentrantlock和读写锁
1 可以手动实现一个类似reentrantlock的工具,首先要维护一个state的标志,代表当前是否有线程已经使用资源。线程lock的时候,
会用cas给state加1,其他线程检测状态。另外需要维护一个等待队列,争夺不到资源的线程统一挂起(park),等线程unlock的时候,
标志减为0,同时从队列里挑一个线程unpark唤醒,继续得到资源操作;如果想让队列线程竞争,就都唤醒,最终只有一个得到资源。
这是实现了基本的锁。
public class LkLock {
private ReentrantLock lock;
private Thread ownerThread;
private LinkedBlockingQueue<Thread> waitList = new LinkedBlockingQueue<Thread>(10000);
private static Unsafe unsafe =null;
private int state=0;
private static long stateOffset;
public LkLock(){
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe"); //Internal reference
f.setAccessible(true);
unsafe = (Unsafe) f.get(null);
stateOffset= unsafe.objectFieldOffset(LkLock.class.getDeclaredField("state"));
} catch (Exception e) {
System.out.println(e+" error");
}
}
public void lock(){
if(compareAndSetState(0,1)){
ownerThread=Thread.currentThread();
}else{
acquire(1);
}
}
public void unlock(){
compareAndSetState(1,0);
if(!CollectionUtils.isEmpty(waitList)){
Thread t=waitList.poll();
LockSupport.unpark(t);
}
}
private void acquire(int i){
try {
//加入等待队列
waitList.put(Thread.currentThread());
//挂起
LockSupport.park();
} catch (InterruptedException e) {
System.out.println(e);
}
}
public int getState() {
return state;
}
private boolean compareAndSetState(int src, int target){
return unsafe.compareAndSwapInt(this, stateOffset, src, target);
}
}
2 同样 如果想要实现能够重入的读写锁,读可重入,写唯一,并且读写互斥,那么需要用两个资源分别给读写的线程竞争,
读的资源可累加,每次线程readlock的时候加一,不设上限;写的线程如上面只可唯一线程获得资源。并且无论读写线程竞争资源之前,
都要检测对方资源是否已经被占用,如果占用也要挂起,这样可以达到互斥。改动如下
public void readLock(){
if(writeState!=0){
acquire();
}
if(compareAndSetReadState(readState,readState+1)){
System.out.println(readState+" 读 我看到的 "+Thread.currentThread());
}else{
acquire();
}
}
public void readUnlock(){
compareAndSetReadState(readState,readState-1);
if(!CollectionUtils.isEmpty(waitList)){
while (waitList.size()!=0){
Thread t=waitList.poll();
LockSupport.unpark(t);
}
}
}
public void writeLock(){
if(readState!=0){
acquire();
}
if(compareAndSetWriteState(0,1)){
System.out.println(writeState+" 写 我看到的 "+Thread.currentThread());
}else{
acquire();
}
}
public void writeUnlock(){
compareAndSetWriteState(1,0);
if(!CollectionUtils.isEmpty(waitList)){
while (waitList.size()!=0){
Thread t=waitList.poll();
LockSupport.unpark(t);
}
}
}
实现reentrantlock和读写锁的更多相关文章
- 多线程并发编程之显示锁ReentrantLock和读写锁
在Java5.0之前,只有synchronized(内置锁)和volatile. Java5.0后引入了显示锁ReentrantLock. ReentrantLock概况 ReentrantLock是 ...
- ReentrantLock和读写锁
在Java5.0之前,只有synchronized(内置锁)和volatile. Java5.0后引入了显示锁ReentrantLock. ReentrantLock概况 ReentrantLock是 ...
- 201709020工作日记--synchronized、ReentrantLock、读写锁
1.reentrantLock java.util.concurrent.lock 中的Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 Java 类,而不是作为语言的特性来实现.这就为Lock ...
- 架构师养成记--14.重入锁ReentrantLock 和 读写锁 ReentrantReadWriteLock
ReentrantLock 有嗅探锁定和多路分支等功能,其实就是synchronized,wait,notify的升级. this锁定当前对象不方便,于是就有了用new Object()来作为锁的解决 ...
- 【漫画】读写锁ReadWriteLock还是不够快?再试试StampedLock!
本文来源于公众号[胖滚猪学编程] 转载请注明出处! 在互斥锁ReentrantLock不好用?试试读写锁ReadWriteLock一文中,我们对比了互斥锁ReentrantLock和读写锁ReadWr ...
- Java并发-显式锁篇【可重入锁+读写锁】
作者:汤圆 个人博客:javalover.cc 前言 在前面并发的开篇,我们介绍过内置锁synchronized: 这节我们再介绍下显式锁Lock 显式锁包括:可重入锁ReentrantLock.读写 ...
- 【漫画】互斥锁ReentrantLock不好用?试试读写锁ReadWriteLock
ReentrantLock完美实现了互斥,完美解决了并发问题.但是却意外发现它对于读多写少的场景效率实在不行.此时ReentrantReadWriteLock来救场了!一种适用于读多写少场景的锁,可以 ...
- 深刨显式锁ReentrantLock原理及其与内置锁的区别,以及读写锁ReentrantReadWriteLock使用场景
13.显示锁 在Java5.0之前,在协调对共享对象的访问时可以使用的机制只有synchronized和volatile.Java5.0增加了一种新的机制:ReentrantLock.与之前提到过的机 ...
- 【java并发编程】ReentrantLock 可重入读写锁
目录 一.ReentrantLock可重入锁 二.ReentrantReadWriteLock读写锁 三.读锁之间不互斥 欢迎关注我的博客,更多精品知识合集 一.ReentrantLock可重入锁 可 ...
随机推荐
- 关于随机浏览头伪装fake-UserAgent
使用: from fake_useragent import UserAgent ua = UserAgent() #ie浏览器的user agent print(ua.ie) Mozilla/5.0 ...
- RockerMQ connect to<:10009>fail
producer端发送报错 com.alibaba.rocketmq.client.exception.MQClientException: Send [] times, still failed, ...
- 从性能角度分析一下String,List,Map
使用String.subString()方法的时候注意内存溢出的问题 public static void testH() { List<String> strings = new Arr ...
- 【Flask】下载多个文件
使用zipfile模块可以将多个文件打包成zip文件进行下载,但是常规的操作方式会在服务器磁盘上生成一个zip文件占用磁盘空间. 后引入BytesIO将文件写入到内存中然后下载: def dl_pla ...
- day6 装饰器总结
装饰器:开放封闭原则,为一个函数加上新的功能,不改变原函数,不改变调用方式 def fun2(wtf): def fun3(): print('i am pythoner!!! ') wtf() re ...
- 算法(Algorithms)第4版 练习 2.2.26
在sort函数创建aux数组: package com.qiusongde; import edu.princeton.cs.algs4.In; import edu.princeton.cs.alg ...
- HDU 4336 Card Collector:期望dp + 状压
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4336 题意: 一共有n种卡片.每买一袋零食,有可能赠送一张卡片,也可能没有. 每一种卡片赠送的概率为p ...
- 分享知识-快乐自己:java代码 操作 solr
POM 文件: <!-- solr客户端 --> <dependency> <groupId>org.apache.solr</groupId> < ...
- 分享知识-快乐自己:PageHelper 分页关键基础代码
关键代码:点我下载样式 详细介绍 //使用分页插件 jQuery("#pagination").pagination(data.total, { items_per_page: ...
- poj3352 边-双联通分量
题意:给一个无向图,问最少加几条边变成边-双联通 题解:求一次双联通,缩点,这样就变成了一棵树,结果就是(树上的叶子节点+1)/2,叶子节点可以通过入度判断 #include<map> # ...