实现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);
}
}

}

 

posted @ 2017-03-27 17:20  练拳码农  阅读(1253)  评论(0编辑  收藏  举报