多线程开发-ReentrantLock 可重复锁详解
程序员文章站
2022-05-04 11:41:48
多线程开发 ReentrantLock 可重复锁详解Condition await条件变量阻塞Conditionsignal条件变量唤醒ReentrantLocklock 获得锁ReentrantLock unlock 释放锁lockInterruptibly作用:持有锁的线程长期不释放的时候,正在等待的线程可以选择放弃等待new ReentrantLock();默认是非公平锁new ReentrantLock(false); 公平锁tryLock......
多线程开发 ReentrantLock 可重复锁详解
- Condition await 条件变量阻塞
- Condition signal 条件变量唤醒
- ReentrantLock lock 获得锁
- ReentrantLock unlock 释放锁
- lockInterruptibly 作用:持有锁的线程长期不释放的时候,正在等待的线程可以选择放弃等待
- new ReentrantLock(); 默认是非公平锁
- new ReentrantLock(false); 公平锁
- tryLock 多选一, 当A获得锁的时候,B探测到A获得锁后就不会再去获取锁了
- tryLock(n,m) 前提:m:TimeUnit.SECONDS ,逻辑:跟tryLock一样,区别:但等待n秒后再去检测
- isHeldByCurrentThread 查询当前线程是否保持此锁
- 1、Condition await 条件变量阻塞
- 2、Condition signal 条件变量唤醒
- 3、ReentrantLock lock 获得锁
- 4、ReentrantLock unlock 释放锁
例子说明:
package yzy_test.com.test;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import com.alibaba.fastjson.JSON;
class ConditionDemo {
private ReentrantLock lock = new ReentrantLock();
//条件变量1
private Condition take = lock.newCondition();
//条件变量2
private Condition put = lock.newCondition();
//阻塞队列(先进先出)
private BlockingQueue queue = new ArrayBlockingQueue<>(10000);
// 队列的最大容量
private int capacity = 5;
// 初始值
private int i = 1;
//往队列里面插入数据
public void put() {
lock.lock(); //获得锁
System.out.println(String.format("【put】i=%d 获取锁!!!", i));
try {
//使用while的目的:它醒了之后你得用while循环让它再去判断一次条件
while (queue.size() == capacity) {
System.out.println(String.format("【put】插入 %d 时队列满,执行put.await!队列值:【%s】", i,JSON.toJSONString(queue.toArray())));
put.await();//条件阻塞
}
queue.put(i);
System.out.println(String.format("【put】插入 %d 到队列", i));
i++;
// 读操作唤醒
take.signal(); //条件唤醒
} catch (Exception e) {
} finally {
System.out.println(String.format("【put】i=%d 释放锁!!!", i - 1));
lock.unlock(); //释放锁 一般放在finally里
}
}
/**
* 从队列读数据
*/
public void take() {
lock.lock(); //获取锁
System.out.println("【take】获取锁!");
int data = 0;
try {
//使用while的目的:它醒了之后你得用while循环让它再去判断一次条件
while (queue.size() == 0) {
System.out.println("【take】执行take.await!");
take.await();//条件阻塞
}
data = (int) queue.take();
System.out.println(String.format("【take】从队列读取值 %d ,队列值:【%s】", data, JSON.toJSONString(queue.toArray())));
// 写操作唤醒
put.signal();//条件唤醒
} catch (Exception e) {
} finally {
System.out.println(String.format("【take】i=%d 释放锁!!!", data));
lock.unlock(); //释放锁 一般放在finally
}
}
}
public class ConditionTest {
// 写任务
static class WriteTask implements Runnable {
private ConditionDemo condition;
public WriteTask(ConditionDemo condition){
this.condition = condition;
}
@Override
public void run() {
condition.put();
}
}
// 读任务
static class ReadTask implements Runnable {
private ConditionDemo condition;
public ReadTask(ConditionDemo condition){
this.condition = condition;
}
public void run() {
condition.take();
}
}
public static void main(String[] args) throws InterruptedException {
ConditionDemo condition = new ConditionDemo();
//类似于一个线程池的功能
for (int i = 0; i < 20; i++) {
new Thread(new WriteTask(condition)).start();;
}
for (int i = 0; i < 20; i++) {
new Thread(new ReadTask(condition)).start();;
}
}
}
效果:
- 5、lockInterruptibly 作用:持有锁的线程长期不释放的时候,正在等待的线程可以选择放弃等待
- 6、new ReentrantLock(); 默认是非公平锁
- 7、new ReentrantLock(false); 公平锁
例子说明:
package yzy_test.com.test;
import java.util.concurrent.locks.ReentrantLock;
/**
* lockInterruptibly() 作用:持有锁的线程长期不释放的时候,正在等待的线程可以选择放弃等待
* 创建一个非公平锁,默认是非公平锁
* Lock lock = new ReentrantLock();
* Lock lock = new ReentrantLock(false);
* */
class LockTest{
//非公平锁
final ReentrantLock lock = new ReentrantLock();
static Boolean flag_one = false;
static Boolean flag_two = false;
static Boolean flag_three = false;
Thread test_one = new Thread(new Runnable() {
public void run() {
try {
lock.lock();
long startTime = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"开始执行:");
while(!flag_one) {
long endTime = System.currentTimeMillis();
//3秒自动中断,防止死锁设计
if((endTime-startTime)/1000 == 3) {
flag_one = true;
System.out.println(Thread.currentThread().getName()+"执行结束,线程中断失败耗时"+((endTime-startTime)/1000)+"秒自动中断");
return;
}
}
long endTime = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"执行结束,线程中断成功耗时"+((endTime-startTime)/1000)+"秒");
}finally {
lock.unlock();
}
}
});
Thread test_two = new Thread(new Runnable() {
public void run() {
try {
lock.lock();
long startTime = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"开始执行:");
while(!flag_two) {
try {
Thread.sleep(200);
long endTime = System.currentTimeMillis();
//3秒自动中断,防止死锁设计
if((endTime-startTime)/1000 == 3) {
flag_two = true;
System.out.println(Thread.currentThread().getName()+"执行结束,线程中断失败,线程中断耗时"+((endTime-startTime)/1000)+"秒自动中断");
return;
}
}catch(Exception e) {
flag_two = true;
}
}
long endTime = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"执行结束,线程中断成功耗时"+((endTime-startTime)/1000)+"秒");
}finally {
lock.unlock();
}
}
});
Thread test_three = new Thread(new Runnable() {
public void run() {
try {
lock.lock();
long startTime = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"开始执行:");
while(!flag_three) {
//配合 线程interrupt()使用,抛出异常,中断线程
lock.lockInterruptibly();
long endTime = System.currentTimeMillis();
//3秒自动中断,防止死锁设计
if((endTime-startTime)/1000 == 3) {
flag_three = true;
System.out.println(Thread.currentThread().getName()+"执行结束,线程中断失败耗时"+((endTime-startTime)/1000)+"秒自动中断");
return;
}
}
long endTime = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"执行结束,线程中断成功耗时"+((endTime-startTime)/1000)+"秒");
} catch(Exception e){
e.printStackTrace();
flag_three = true;
}finally {
lock.unlock();
}
}
});
}
public class ReentrantLockTest {
public static void main(String[] args) throws InterruptedException {
LockTest test = new LockTest();
//ReentrantLock lock 无try/catch执行
test.test_one.start();
test.test_one.setName("线程A:ReentrantLock lock 无try/catch执行");
Thread.sleep(2000);
test.test_one.interrupt();
//ReentrantLock lock 有try/catch执行
test.test_two.start();
test.test_two.setName("线程B:ReentrantLock lock try/catch执行");
Thread.sleep(2000);
test.test_two.interrupt();
//ReentrantLock lockInterruptibly try/catch执行
test.test_three.start();
test.test_three.setName("线程C:ReentrantLock lockInterruptibly try/catch执行");
Thread.sleep(2000);
test.test_three.interrupt();
}
}
效果:
- 8、tryLock 多选一, 当A获得锁的时候,B探测到A获得锁后就不会再去获取锁了
- 9、tryLock(n,m) 前提:m:TimeUnit.SECONDS ,逻辑:跟tryLock一样,区别:但等待n秒后再去检测
- 10、isHeldByCurrentThread 查询当前线程是否保持此锁
例子说明:
package yzy_test.com.test;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/**
* tryLock 多选一, 当A获得锁的时候,B探测到A获得锁后就不会再去获取锁了
* tryLock(n,m) 前提:m:TimeUnit.SECONDS ,逻辑:跟tryLock一样,区别:但等待n秒后再去检测
* isHeldByCurrentThread 查询当前线程是否保持此锁
* */
public class RunTryLockTest {
private long time ;
public RunTryLockTest(long time) {
this.time = time;
}
public ReentrantLock lock = new ReentrantLock();
public void TryLockTest(){
try {
if (lock.tryLock()){
System.out.println(Thread.currentThread().getName()+"--获得锁");
} else {
System.out.println(Thread.currentThread().getName()+"--没有获得锁");
}
} finally {
if (lock.isHeldByCurrentThread()){
lock.unlock();
}
}
}
public void TryLockTestTime(){
long startTime = System.currentTimeMillis();
try {
//等待3秒后再去探寻是否有其他线程保持锁
if(lock.tryLock(3, TimeUnit.SECONDS)) {
Thread.sleep(time);
System.out.println(Thread.currentThread().getName()+"--开始获得锁");
} else {
System.out.println(Thread.currentThread().getName()+"--没有获得锁");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//查询当前线程是否保持此锁
if (lock.isHeldByCurrentThread()){
lock.unlock();
long endTime = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"释放锁耗时:"+((endTime-startTime)));
}
}
}
public static void main(String[] args) throws InterruptedException {
final long time = 4000;
final RunTryLockTest test = new RunTryLockTest(time);
Runnable tryLockTest = new Runnable() {
@Override
public void run() {
test.TryLockTest();
}
};
Runnable tryLockTestTime = new Runnable() {
@Override
public void run() {
test.TryLockTestTime();
}
};
Thread t1 = new Thread(tryLockTest);
t1.setName("tryLock 例子1");
Thread t2 = new Thread(tryLockTest);
t2.setName("tryLock 例子2");
Thread t3 = new Thread(tryLockTestTime);
t3.setName("tryLockTime 例子1");
Thread t4 = new Thread(tryLockTestTime);
t4.setName("tryLockTime 例子2【添加时长"+time+"】");
//同步执行测试:
//执行tryLock
t1.start();
t2.start();
t1.join();
t2.join();
//执行 tryLockTime
t3.start();
t4.start();
t3.join();
t4.join();
}
}
效果:
本文地址:https://blog.csdn.net/weixin_38316697/article/details/107334049
上一篇: 朱厚照是怎么自己把自己给玩死的?