1 可以手动实现一个类似reentrantlock的工具,首先要维护一个state的标志,代表当前是否有线程已经使用资源。线程lock的时候,
会用cas给state加1,其他线程检测状态。另外需要维护一个等待队列,争夺不到资源的线程统一挂起(park),等线程unlock的时候,
标志减为0,同时从队列里挑一个线程unpark唤醒,继续得到资源操作;如果想让队列线程竞争,就都唤醒,最终只有一个得到资源。
这是实现了基本的锁。
public class LkLock {
private ReentrantLock lock; private Thread ownerThread; private LinkedBlockingQueuewaitList = new LinkedBlockingQueue (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); } } }