1.Lock接口
/**
* 定义锁接口
* 接口支持那些语义不同(重入、公平等)的锁规则,可以在非阻塞式结构的上下文(包括 hand-over-hand 和锁重排算法)中使用这些规则。
* 主要的实现是 ReentrantLock。
*/
public interface Lock {
/*在Lock中声明了四个方法来获取锁,那么这四个方法有何区别呢?
* 首先,lock()方法是平常使用得最多的一个方法,就是用来获取锁。
* 如果锁已被其他线程获取,则进行等待。
* 在前面已经讲到,如果采用Lock,必须主动去释放锁,并且在发生异常时,不会自动释放锁。
* 因此,一般来说,使用Lock必须在try…catch…块中进行,并且将释放锁的操作放在finally块中进行,以保证锁一定被被释放,防止死锁的发生。
*/
/** 获取锁 */
void lock();
/*lockInterruptibly()方法比较特殊,当通过这个方法去获取锁时,
* 如果线程 正在等待获取锁,则这个线程能够 响应中断,即中断线程的等待状态。
* 例如,当两个线程同时通过lock.lockInterruptibly()想获取某个锁时,假若此时线程A获取到了锁,而线程B只有在等待,
* 那么对线程B调用threadB.interrupt()方法能够中断线程B的等待过程。
*/
/** 如果当前线程未被中断,则获取锁,可以响应中断 */
void lockInterruptibly() throws InterruptedException;
/*tryLock()方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true;
* 如果获取失败(即锁已被其他线程获取),则返回false,
* 也就是说,这个方法无论如何都会立即返回(在拿不到锁时不会一直在那等待)
*/
/** 仅在调用时锁为空闲状态才获取该锁,可以响应中断 */
boolean tryLock();
/*tryLock(long time, TimeUnit unit)方法和tryLock()方法是类似的,
* 只不过区别在于这个方法在拿不到锁时会等待一定的时间,在时间期限之内如果还拿不到锁,就返回false,
* 同时可以响应中断。如果一开始拿到锁或者在等待期间内拿到了锁,则返回true。
*/
/** 如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁 */
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
/** 释放锁 */
void unlock();
/** 返回绑定到此 Lock 实例的新 Condition 实例 */
Condition newCondition();
}
2.ReadWriteLock接口
/** 读写锁接口 */
public interface ReadWriteLock {
/** 获取读锁 */
Lock readLock();
/** 获取写锁 */
Lock writeLock();
}
3.Condition接口
/**
* 接口描述了可能会与锁有关联的条件变量。 使用时需要和一个Lock绑定
* 这些变量在用法上与使用 Object.wait 访问的隐式监视器类似,但提供了更强大的功能。
* 需要特别指出的是,单个 Lock 可能与多个 Condition 对象关联。
* 为了避免兼容性问题,Condition 方法的名称与对应的 Object 版本中的不同。
*/
public interface Condition {
/** 调用此方法的线程将加入等待队列,阻塞直到被通知或线程发生中断 */
void await() throws InterruptedException;
/** 调用此方法的线程将加入等待队列,阻塞 直到被通知*/
void awaitUninterruptibly();
/** 调用此方法的线程加入等待队列,阻塞直到被通知或发生中断或者超出等待的时间 */
long awaitNanos(long nanosTimeout) throws InterruptedException;
/** 调用此方法的线程加入等待队列,阻塞直到被通知或发生中断或者超出等待的时间 (指定时间单位)*/
boolean await(long time, TimeUnit unit) throws InterruptedException;
/** 调用此方法的线程加入等待队列,阻塞直到被通知或发生中断或者超出特定的日期时间 */
boolean awaitUntil(Date deadline) throws InterruptedException;
/** 唤醒一个等待中的线程 */
void signal();
/** 唤醒所有等待中的线程 */
void signalAll();
}
4.LockSupport类
/**
* LockSupport是一个线程阻塞工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞或唤醒
*/
@SuppressWarnings("unused")
public class LockSupport {
private LockSupport() {} // Cannot be instantiated.
private static void setBlocker(Thread t, Object arg) {
UNSAFE.putObject(t, parkBlockerOffset, arg);
}
/** 恢复当前线程 */
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
/** 暂停当前线程 */
public static void park() {
UNSAFE.park(false, 0L);
}
public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, 0L);
setBlocker(t, null);
}
/** 暂停当前线程,不过有超时时间的限制 */
public static void parkNanos(long nanos) {
if (nanos > 0)
UNSAFE.park(false, nanos);
}
public static void parkNanos(Object blocker, long nanos) {
if (nanos > 0) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, nanos);
setBlocker(t, null);
}
}
/** 暂停当前线程,直到某个时间 */
public static void parkUntil(long deadline) {
UNSAFE.park(true, deadline);
}
public static void parkUntil(Object blocker, long deadline) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(true, deadline);
setBlocker(t, null);
}
public static Object getBlocker(Thread t) {
if (t == null)
throw new NullPointerException();
return UNSAFE.getObjectVolatile(t, parkBlockerOffset);
}
static final int nextSecondarySeed() {
int r;
Thread t = Thread.currentThread();
if ((r = UNSAFE.getInt(t, SECONDARY)) != 0) {
r ^= r << 13; // xorshift
r ^= r >>> 17;
r ^= r << 5;
}
else if ((r = java.util.concurrent.ThreadLocalRandom.current().nextInt()) == 0)
r = 1; // avoid zero
UNSAFE.putInt(t, SECONDARY, r);
return r;
}
private static final sun.misc.Unsafe UNSAFE;
private static final long parkBlockerOffset;
private static final long SEED;
private static final long PROBE;
private static final long SECONDARY;
static {
try {
UNSAFE = sun.misc.Unsafe.getUnsafe();
Class<?> tk = Thread.class;
parkBlockerOffset = UNSAFE.objectFieldOffset
(tk.getDeclaredField("parkBlocker"));
SEED = UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomSeed"));
PROBE = UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomProbe"));
SECONDARY = UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomSecondarySeed"));
} catch (Exception ex) { throw new Error(ex); }
}
}