手动实现一个可重入锁
下面代码给出了一个手动实现的可重入锁,MyLock类,实现了Lock接口,需要编写的两个函数为lock()和unlock()。isLocked变量用来判断当前是否有线程使用,若没有,则为false。lockBy变量保存了当前持有的线程。lockcount变量保存当前持有的线程的计数器。函数中调用wait()和notify()时,需要加上关键字synchronized。
package com.concur.class21;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
public class MyLock implements Lock{
private boolean isLocked=false;
private Thread lockBy=null;
private int lockcount=0;
@Override
public synchronized void lock() {
Thread currentThread=Thread.currentThread();//1
while(isLocked&¤tThread!=lockBy)){//2
try {
wait();//3
} catch (InterruptedException e) {
e.printStackTrace();
}
}
isLocked=true;//4
lockBy=currentThread;//5
lockcount++;//6
}
@Override
public synchronized void unlock() {
if(lockBy==Thread.currentThread()){//7
lockcount--;//8
if(lockcount==0){//9
notify();//10
isLocked=false;//11
}
}
}
@Override
public void lockInterruptibly() throws InterruptedException {
// TODO Auto-generated method stub
}
@Override
public boolean tryLock() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
// TODO Auto-generated method stub
return false;
}
@Override
public Condition newCondition() {
// TODO Auto-generated method stub
return null;
}
}
下面结合实例来分析上面手动实现的可重入锁,首先设计了一个Test类,定义了两个函数a()和b(),在函数a()中加锁并调用b()函数,在b()函数中,同样进行加锁操作。
当只有一个线程时:
- 进入函数a(),首先调用lock.lock()函数,执行步骤1,此时currentThread=thread0,执行步骤2,isLocked=false,currentThread=thread0,lockBy=null,并不进入while循环,则执行步骤4-6,isLocked=true,lockBy=thread0,lockcount=1
- 进入函数b(),同样调用lock()函数,执行步骤1,此时currentThread=thread0,执行步骤2,isLocked=true,currentThread=lockBy,不满足条件,并不进入while循环,则执行步骤4-6,isLocked=true,lockBy=thread0,lockcount=2
- 调用函数b()中的unlock()函数,执行步骤7,lockBy=thread0=Thread.currentThread,则执行步骤8,lockcount=1,退出函数
- 接着调用函数a()中的unlock()函数,执行步骤7,同样满足判断,lockcount=0,执行步骤10-11,调用notify()函数通知其他线程,并设置isLocked变量为false。
当有多个线程竞争时:
通过比较currentThread变量(当前想要获取锁的线程)和lockBy(当前已经持有锁的线程)进行比较,如果不相同,则调用wait()函数,直到有线程调用notify()通知。
package com.concur.class21;
import java.util.concurrent.locks.Lock;
public class Test {
Lock lock=new MyLock();
public void a(){
lock.lock();
System.out.println("a");
b();
lock.unlock();
}
public void b(){
lock.lock();
System.out.println("b");
lock.unlock();
}
public static void main(String[] args) {
Test test=new Test();
new Thread(new Runnable() {
@Override
public void run() {
test.a();
}
}).start();
}
}
输出结果:
a
b