介绍Lock,可以代替synchronized关键字,大量的并发包使用了lock。
- ReentrantLock类
- ReentrantReadWriteLock 类
1、基本用法
通过lock和unlock进行上锁和解锁
Lock lock = new ReentrantLock();
void method(){
lock.lock();
//代码巴拉巴拉巴拉
locak.unlock();
}
2、condition用于通知
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
//等待
void method(){
lock.lock();
condition.await();
lock.unlock();
}
//通知
void method(){
lock.lock();
condition.signal();
lock.unlock();
}
针对不同线程,可以建立多个condition。实现通知部分线程。
构建Lock时,传递boolean值可以设置公平锁和不公平锁
lock = new ReentrantLock(false); // 不公平
3、方法getHoldCount、getQueueLength、getWaitQueueLength
- getHoldCount:查询持有lock的线程的个数(线程内可以套用线程,因此lock块内也可以套用lock)
- getQueueLength: 返回等待lock的线程的个数
- getWaitQueueLength(Condition condition):返回condition.await()(等待notify)的线程个数
4、方法hasQueuedThread、hasQueuedThreads、hasWaiters
- lock.hasQueueThread(Thread thread): 查询指定的线程是否在等待获取此锁
- lock.hasQueuedThreads():查询是否有线程等待此锁
- lock.hasWaiters(Condition condition):查询是否有线程正在等待和此condition相关。
- lock.getWaitQueueLength(Condition condition):查询等待此condition的线程个数
5、方法isFair、isHeldByCurrentThread、isLocked
- lock.isFair(): 判断锁lock是否是公平锁
- lock.isHeldByCurrentThread():判断当前线程是否持有lock
- lock.isLocked():判断lock是否被锁定
6、lockInterruptibly、tryLock、tryLock(long timeout,TimeUnit unit)
- lock.lockInterruptibly(): 如果当前线程没有被中断,则获取这个锁,否则抛出异常。
- lock.tryLock():如果lock没有被线程获取,那么当前线程就获取该锁。
- lock.tryLock(time,timeUnit):等待time,如果time期间lock都没有被锁定,那么获取该锁。
7、awaitUninterruptiby()
如果进程在调用condition.await()时被其他进程interrupt,那么就会引发异常,如果调用的是condition.awaitUninterruptiby(),那么就不会有异常发生。
8、awaitUntil(Calendar calendar) 规定时间内会自动唤醒
9、实现线程按序执行
import javax.security.auth.Subject;
import java.util.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Main {
volatile private static int nextPrintWho = 1;
private static ReentrantLock lock = new ReentrantLock();
final private static Condition conditionA = lock.newCondition();
final private static Condition conditionB = lock.newCondition();
public static void main(String[] args) {
Thread threadA = new Thread(){
@Override
public void run() {
try{
lock.lock();
while (nextPrintWho != 1)
conditionA.await();
for (int i = 0; i < 3; i++) {
System.out.println("ThreadA: " + i);
}
nextPrintWho = 2;
conditionB.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
};
Thread threadB = new Thread(){
@Override
public void run() {
try{
lock.lock();
while (nextPrintWho != 2)
conditionB.await();
for (int i = 0; i < 3; i++) {
System.out.println("ThreadB: " + i);
}
nextPrintWho = 1;
conditionA.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
};
Thread[] aArray = new Thread[5];
Thread[] bArray = new Thread[5];
for (int i = 0; i < 5; i++) {
aArray[i] = new Thread(threadA);
bArray[i] = new Thread(threadB);
aArray[i].start();
bArray[i].start();
}
}
}
10、更高效的lock – ReentrantReadWriteLock
ReentrantReadWriteLock提供了读锁,写锁。
只有写锁之间互斥,读锁和写锁之间互斥。其他锁之间共享。
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
//读锁
lock.readLock.lock();
lock.readLock.unlock();
//写锁
lock.writeLock.lock();
lock.writeLock.unlock();