1、可重入锁ReentrantLock,相当于synchronized块,为临界区提供互斥访问机制。

(1) 相关的接口

创建一个可重入锁

Lock lock = new ReentrantLock();
请求锁,如果锁被当前另一个线程持有,则阻塞。

void lock();
释放锁

void unlock();
非阻塞型lock()

boolean tryLock();

(2) 使用基本结构

locker.lock();
try{
//code here to access the cirtical section
}finally{
locker.unlock();
}
  这种结构保证在任何时刻只有一个线程能够进入临界区,如果一个线程锁住了锁对象,其他任何线程在调用lock时,都会被阻塞,直到第一个线程释放锁对象。而且无论try块是否抛出异常,都会执行finally block,解锁locker。

(3) 锁的可重入性

  锁是可重入的,线程能够重复地获取它已经拥有的锁。锁对象维护一个持有计数(hold count)来追踪对lock方法的嵌套调用。线程在每次调用lock后都要调用unlock来释放锁。由于这个特性,被一个锁保护的代码可以调用另一个使用相同锁的方法。

(4) 示例代码:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
 
class WorkerOne extends Thread{
    private Lock locker;
    public WorkerOne (Lock locker){
        this.locker = locker;
    }
    
    public void run(){
        locker.lock();
        try{
System.out.println(Thread.currentThread().getName()+":step into critical section");
        }finally{
            locker.unlock();    
        }
    }
}
 
class WorkerTwo extends Thread{
    private Lock locker;
    public WorkerTwo (Lock locker){
        this.locker = locker;
    }
    
    public void sayHello(){
        locker.lock();
        try{    System.out.println(Thread.currentThread().getName()+":call sayHello()");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            locker.unlock();
        }
    }
    
    public void run(){
        locker.lock();  
        try{        System.out.println(Thread.currentThread().getName()+":setp into critical section");
                        //测试锁的可重入性 
            sayHello();
        }finally{
            locker.unlock();    
        }
    }
}
 
public class Test5 {
    public static void main(String[] args) {
        Lock locker = new ReentrantLock();
        WorkerOne wo= new WorkerOne(locker);
        wo.setName("WorkerOne");
        WorkerTwo wt = new WorkerTwo(locker);
        wt.setName("WorkerTwo");
        
        wt.start();
        wo.start(); 
    }
}