学生管理系统网站此网站不支持下载视频怎么办
ReentrantLock
- ReentrantLock与Synchronized
- 工作原理
- Condition
ReentrantLock与Synchronized
ReentrantLock是一种可重入的独占锁,相对于synchronized,ReentrantLock具备如下特点:
- 可中断
- 可以设置超时时间
- 可以设置为公平锁
- 支持多个条件变量
- 与synchronized一样,都支持可重入
在使用时要注意4个问题:
- 默认情况下ReentrantLock为非公平锁而非公平锁;
- 加锁次数和释放锁次数一定要保持一致,否则会导致线程阻塞或程序异常;
- 加锁操作一定要放在try代码之前,这样可以避免未加锁成功又释放锁的异常;
- 释放锁一定要放在finally中,否则会导致线程阻塞。
工作原理
当有线程调用lock方法的时候:如果线程获取到锁了,那么就会通过CAS的方式把AQS内部的state设置成为1。这个时候,当前线程就获取到锁了。只有首部的节点(head节点封装的线程)可以获取到锁。其他线程都会加入到这一个阻塞队列当中。如果是公平锁的话,当head节点释放锁之后,会优先唤醒head.next这一个节点对应的线程。如果是非公平锁,
允许新来的线程和head之后唤醒的线程通过cas竞争锁。
Condition
相当于synchronized中的wait()和notify()机制,通常与Lock接口(比如ReentrantLock)一起使用。调用Condition的await()和signal()方法,都必须在lock保护之内。
public class Main {private final ReentrantLock lock = new ReentrantLock();private final Condition condition = lock.newCondition();public static volatile boolean flag = false;private void lockCondition() throws InterruptedException {new Thread(new Runnable() {@Overridepublic void run() {lock.lock();try {System.out.println("t1线程抢到锁");while (!flag) {System.out.println("t1线程等待");condition.await();}} catch (InterruptedException e) {throw new RuntimeException(e);} finally {lock.unlock();System.out.println("t1线程释放锁");}System.out.println("线程t1执行完成");}}, "t1").start();Thread.sleep(3000);new Thread(new Runnable() {@Overridepublic void run() {lock.lock();try {System.out.println("t2线程抢到锁");flag = true;condition.signal();} finally {lock.unlock();System.out.println("t2线程释放锁");}System.out.println("t2线程执行完成");}}, "t2").start();}public static void main(String[] args) throws InterruptedException {new Main().lockCondition();}
}