lock锁
public class LockDemo {
private Lock lock = new ReentrantLock();
private int count = 0;
public int inc() {
lock.lock();
try {
int newCount = count++;
} finally {
//保证锁最终被释放
lock.unlock();
}
return newCount;
}
}
ReentrantLock()是实现lock接口的子类,调用lock的lock()方法对非原子性操作进行锁定,使用try finally 保证在出现异常时,锁能够最终被释放。
实现自己可重入的MyLock
- 什么是可重入锁
private MyLock mylock =new MyLock();
public void getA(){
mylock.lock();
System.out.println("调用a方法");
getB();
mylock.unlock();
}
public void getB(){
mylock.lock();
System.out.println("调用b方法");
mylock.unlock();
}
getA()和getB()使用的是同一个mylock锁,所以getA()中调用getB()的操作就被视为是锁的重入。
如果一个线程已经拥有了一个管程对象上的锁,那么它就有权访问被这个管程对象同步的所有代码块。这就是可重入。线程可以进入任何一个它已经拥有的锁所同步着的代码块。
public class MyLock {
private boolean flag=false;
private int count = 0;//记录加锁次数
private Thread thread = null;//记录当前线程
public synchronized void lock() {
try {
Thread callingThread = Thread.currentThread();
//自旋
while (flag && thread != callingThread )
wait();
flag=true;
count++;
thread = callingThread;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void unlock() {
//是当前线程
if (Thread.currentThread() == this .thread){
//将计数器置为0
count--;
if (count == 0){
flag=false;
thread=null;
notify();
}
}
flag=false;
notify();
}
}
重入锁的关键是保证同一个线程持有锁,如果flag=true并且不是当前线程(flag && thread != callingThread ),让其它线程自选等待。
接下来讨论公平锁和读写锁