实现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可重入锁 可 ...
随机推荐
- Hadoop Pig
Pig包括两部分: 用于描述数据流的语言,称为Pig Latin. 用于执行Pig Latin程序的执行环境,当前有两个环境:单JVM中的本地执行环境和Hadoop集群上的分布式执行环境. Pig内部 ...
- Oracle数据库体系结构(3)数据库进程
一.Oracle进程概述 在oracle中进程分为用户进程(User Process).服务器进程(server process)和后天进程3种. 1.用户进程:当用户连接到数据库执行一个应用程序是, ...
- show processlist,sysbench压力测试工具
processlist.sh 记录数据库的状态 #!/bin/bash while true do mysql -uroot -pwangxiaohu -e 'show processlist\G'| ...
- SQL 优化案例
create or replace procedure SP_GET_NEWEST_CAPTCHA( v_ACCOUNT_ID in VARCHAR2, --接收短信的手机号 v_Tail_num i ...
- java访问控制---java编程语言
- java:Eclipse:Could not create the view:解决办法
Eclipse:Could not create the view: Plug-in org.eclipse.jdt.ui was unable to load class org.eclipse.j ...
- spring自动扫描装配bean
applicationContext.xml: <!-- 自动扫描service包,根据包中注解自动装配bean --> <context:component-scan base-p ...
- Git教程(二)-如何上传和同步自己的git项目
本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! Git接触并使用多年, 工作中使用较多,它的分布式存储,使每个人的电脑均为服务器的策略非常棒:再加上 ...
- mfc设置鼠标状态OnSetCursor响应函数
参考文章:1.https://bbs.csdn.net/topics/70084486 2.https://blog.csdn.net/wang15061955806/article/details/ ...
- codeforces 710C C. Magic Odd Square(构造)
题目链接: C. Magic Odd Square Find an n × n matrix with different numbers from 1 to n2, so the sum in ea ...