StampedLock
依据时间戳实现锁机制,用于解决读写锁在读写资源线程数量不平衡时,资源抢占不公平的情况。在该类中支持有三种锁的处理模式,分别为写锁、悲观锁、乐观锁。每一个完整的StampedLock是由版本和模式两个部分所组成,在获取相关锁时会返回有一个数字标记戳,用于控制锁的状态,并利用该标记戳实现解锁的处理。
Condition
在最早学习到多线程技术的时候,会使用Object类之中提供的 wait、notify方法进行等待与唤醒的处理,而后在传统的Thread 类之中,又提供了暂停和恢复的功能(这个功能已经被废除),Condition实现了相同的功能。
Condition是一个接口,可以依靠Lock接口提供的方法来实现。public Condition newCondition()
-
在 ReentranLock 类之中可以发现该方法是由
sync.newCondition()
方法调用的; -
sync对象为 AQS 实现子类,所以最终的
newcondition()
方法是由 AQS 来完成的;public Condition newCondition() { return sync.newCondition(); }
-
sync中实现了
new ConditionObject()
,这是AQS的内部类,实现如下:public class ConditionObject implements Condition, java.io.Serializable { private static final long serialVersionUID = 1173984872572414699L; private transient ConditionNode firstWaiter; private transient ConditionNode lastWaiter; public ConditionObject() { }
经过分析之后可以发现,在Condition内部实际上是将所有的等待的操作线程保存在了队列之中,因为可以依靠AQS提供的CLH机制实现线程的控制。
Condition实现线程的等待与唤醒:
package juc.condition2;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author birdy
* @date 2022/6/25 10:58 AM
*/
public class Main {
public static String msg = null;
public static ReentrantLock reentrantLock = new ReentrantLock();
public static Condition condition = reentrantLock.newCondition();
public static void main(String[] args) {
try {
reentrantLock.lock();
new Thread(() -> {
try {
reentrantLock.lock();
TimeUnit.MILLISECONDS.sleep(2);
System.out.println("sub thread complete!");
msg = "hello!";
condition.signal();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
reentrantLock.unlock();
}
}).start();
condition.await();
} catch (Exception e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
System.out.println("unlocked");
}
System.out.println(msg);
}
}