内部锁(自动锁 JVM管理):通过synchronized关键字实现
显示锁(手动锁 手动管理锁 功能更多):通过java.concurrent.locks.Lock接口的实现类
- ReentrantLock 可重入锁
允许同一线程重复获得该锁不会出现死锁等问题(synchronized就是可重入的)
公平锁:
synchronized默认是非公平锁,公平锁能保证先请求锁的线程拿到锁,避免线程饥饿问题等待过久,但是需要维护有序队列产生额外开销,据情况使用
new ReentrantLock(boolean) true开启公平锁
常用方法:
lock() 获得锁 一般finally里unlock()释放锁,在中间区域属于同步代码块
static Lock lock=new ReentrantLock();
private static void test(){
lock.lock();
同步代码块
lock.unlock();
}
★证明ReentrantLock可重入性(线程1进入test又进入test2重复拿到锁对象) , 以及实现同步:
public class T3{
static final Lock lock=new ReentrantLock();
private static void test(){
lock.lock();
System.out.println(Thread.currentThread().getName()+"开始");
test2();
lock.unlock();
} private static void test2(){
lock.lock();
System.out.println(Thread.currentThread().getName()+"执行2");
lock.unlock();
}
public static void main(String[] args) {
new Thread(T3::test).start();
new Thread(T3::test).start();
}
}
- Lock.lockInterruptibly() 若当前线程未被interrupt()中断则获得锁,若被中断则抛出异常,让出锁
一般搭配isAlive()检测某线程是否活动,是则interrupt()发出中断信号 -
Lock.tryLock() / (long, TimeUnit.SECONDS) 是否未被占有/ 指定秒数内未被占有
interrupt() 同样可以使tryLock()为true -
Condition Lock.newCondition() 返回的类型可以实现 等待/通知唤醒
await() 当前线程丢弃锁进入睡眠
signal() 从等待队列中唤醒第一个线程,使其尝试重新获取锁(一般放在句末搭配unlock释放)
public static void main(String[] args) throws InterruptedException { Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); Thread t1 = new Thread(() -> { lock.lock(); try { System.out.println("线程1获取锁"); condition.await(); while (true){ if(lock.tryLock()){ System.out.println("线程1被唤醒"); //线程2唤醒后回调 break; }else { System.out.println("线程1睡觉中"); //线程2唤醒后回调 } } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } }); Thread t2 = new Thread(() -> { lock.lock(); try { Thread.sleep(1000); //保证t1先启动 System.out.println("线程2获取锁"); condition.signal(); System.out.println("线程2唤醒线程1"); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } }); t1.start(); t2.start(); }
Lock其他常用方法:
int getHoldCount():返回当前线程调用lock()方法的次数
int getQueueLength():返回正在等待获得锁的线程预估数
int getWaitQueueLength(Condition condition):返回与condition条件相关等待线程预估数boolean hasQueuedThreads():是否还有线程在等待获得该锁
boolean hasWaiters(Condition condition):是否有线程在等待指定的condition
boolean isFair():是否为公平锁
boolean isHeldByCurrentThread():判断当前线程是否持有该锁
boolean isLocked():当前锁是否被线程(任意)持有