一、什么是重入锁
锁,是多线程控制临界区资源访问的有效方法。重入锁,顾名思义就是可以对同一个线程进行多次加锁的一个锁类型。对于每一次的加锁都得有对应的解锁。
1.1 重入锁的简单使用
package com.zhaotq.lab.thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockDemo implements Runnable {
public static int value =0;
public static ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
for(int i=0;i<10000;i++){
lock.lock();
value++ ;
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new ReentrantLockDemo(),"thread1");
Thread thread2 = new Thread(new ReentrantLockDemo(),"thread2");
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("执行完毕");
System.out.println(value);
}
}
1.2 中断响应
如1.1例子所示,实用lock方法,如果线程无法获取到锁,则会一直处于阻塞等待状态,知道获取锁以后继续执行。一不小心会出现死锁的现象。同样重入锁具有相应状态的方法。lockInterruptibly 方法优先响应中断。
package com.zhaotq.lab.thread;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockInterruptDemo implements Runnable{
static ReentrantLock lock1 = new ReentrantLock();
static ReentrantLock lock2= new ReentrantLock();
private int i =0;
public ReentrantLockInterruptDemo(int i){
this.i = i ;
}
@Override
public void run() {
if(this.i==1){
try {
lock1.lockInterruptibly();//获取可以被中断的锁
System.out.println("线程被lock1锁定开始进入休眠");
Thread.sleep(2000);
lock2.lockInterruptibly();
} catch (InterruptedException e) {
System.out.println("线程被打断");
e.printStackTrace();
}finally {
//判断当前线程是否用有锁,如果用有锁,则进行释放
System.out.println("当前线程被打断");
if(lock1.isHeldByCurrentThread()){
lock1.unlock();
}
if(lock2.isHeldByCurrentThread()){
lock2.unlock();
}
}
}else{
try {
lock2.lockInterruptibly();
System.out.println("线程被lock2锁定");
Thread.sleep(2000);
lock1.lockInterruptibly();
System.out.println("线程lock2被执行");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//判断当前线程是否用有锁,如果用有锁,则进行释放
if(lock1.isHeldByCurrentThread()){
lock1.unlock();
}
if(lock2.isHeldByCurrentThread()){
lock2.unlock();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new ReentrantLockInterruptDemo(1),"demo1");
Thread thread2 = new Thread(new ReentrantLockInterruptDemo(2),"demo1");
thread1.start();
thread2.start();
System.out.println("开始中断锁");
thread1.interrupt();//如果此处不进行中断则整个程序都会被锁死,而无法进行下去
}
}
1.3 公平锁
ReentrantLock lock = new ReentrantLock(true);//设置公平锁
二、重入锁常用API
方法名称 | 方法描述 |
---|---|
lock | 获得锁,如果所已经被占用则等待 |
lockInterruptibly() | 获得锁,但优先响应中断 |
tryLock() | 尝试获得锁,如果称重则返回true,负责返回false,该方法不等待立即返回 |
tryLock(long time ,TimeUnit unit) | 在给定的时间内尝试获取锁,如果成功则返回true,否则返回false |
unlock() | 释放锁 |
三、重入锁与Condition的配合使用
3.1 创建condition
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newConditon();
3.2 主要方法介绍
方法名称 | 方法描述 |
---|---|
void await() throws InterruptedExcetion; | 当前线程进如等待状态,同时释放锁,使用sign或者signall重新获得锁并继续执行 |
void awaitUninterruptibly() | 当前等待,不响应中断 |
long awaitNanos(long nanosTimeout) throws InterruptedException; | 等待毫秒,超时后响应中断 |
boolean await (long time ,TimeUnit unit)throws InterruptedException; | |
boolean await (Date deadline)throws InterruptedException; | |
void signal(); | 唤醒某一个正在等待的进程 |
void signalAll(); | 唤醒所有的进程 |