重入锁ReentrantLock[Re-entrant Lock]
- ReentrantLock与Synchronized区别:
- 重入锁可以反复进入
lock.lock(); lock.lock(); try{ i++; }finally{ lock.unlock(); lock.unlock(); }
//RentrantLock.java JDK8 /** * Acquires the lock. * * <p>Acquires the lock if it is not held by another thread and returns * immediately, setting the lock hold count to one. * * <p>If the current thread already holds the lock then the hold * count is incremented by one and the method returns immediately. * * <p>If the lock is held by another thread then the * current thread becomes disabled for thread scheduling * purposes and lies dormant until the lock has been acquired, * at which time the lock hold count is set to one. */ public void lock() { sync.lock(); } /** * Attempts to release this lock. * * <p>If the current thread is the holder of this lock then the hold * count is decremented. If the hold count is now zero then the lock * is released. If the current thread is not the holder of this * lock then {@link IllegalMonitorStateException} is thrown. * * @throws IllegalMonitorStateException if the current thread does not * hold this lock */ public void unlock() { sync.release(1); }
- 如果同一个线程多次获得锁,那么在释放锁的时候,也需要释放相同次数
- 若释放锁的次数过多,将会得到 java.lang.IllegalMonitorStateException异常
- 重入锁可以反复进入
- 高级功能
- 中断响应[lockInterruptibly()]:
如果一个线程在等待锁,那么它依然可以收到一个通知,被告知无需再等待,可以停止工作了。
public class IntLock implements Runnable { public static ReentrantLock lock1 = new ReentrantLock(); public static ReentrantLock lock2 = new ReentrantLock(); int lock; public IntLock(int lock) { this.lock = lock; } @Override public void run() { try { if (lock == 1) { lock1.lockInterruptibly(); try { Thread.sleep(500); } catch (InterruptedException e) { } lock2.lockInterruptibly(); } else { lock2.lockInterruptibly(); try { Thread.sleep(500); } catch (InterruptedException e) { } lock1.lockInterruptibly(); } } catch (InterruptedException e) { e.printStackTrace(); } finally { if (lock1.isHeldByCurrentThread()) { lock1.unlock(); } if (lock2.isHeldByCurrentThread()) { lock2.unlock(); } System.out.println(Thread.currentThread().getId() + ":线程退出"); } } public static void main(String[] args) throws InterruptedException { IntLock r1 = new IntLock(1); IntLock r2 = new IntLock(2); Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start(); t2.start(); Thread.sleep(1000); t2.interrupt(); } }
- 锁申请等待限时[tryLock()]:
public class TimeLock implements Runnable{ public static ReentrantLock lock = new ReentrantLock(); @Override public void run(){ try{ if(lock.tryLock(5, TimeUnit.SECONDS)){ Thread.sleep(6000); }else{ System.out.println("get lock failed"); } }catch (InterruptedException e){ e.printStackTrace(); }finally { if(lock.isHeldByCurrentThread()){ lock.unlock(); } } } public static void main(String[] args) { TimeLock tl = new TimeLock(); Thread t1 = new Thread(tl); Thread t2 = new Thread(tl); t1.start(); t2.start(); } }
- 公平锁[public ReentrantLock(boolean fair)]:
- 大多数情况下,锁的申请都是非公平的。系统每次从锁的等待队列中随机挑选一个。
- 当ReentrantLock 的fair参数为true时,锁是公平的。
- 公平锁需要系统维护一个有序队列,实现成本高,性能相对低下。
- 中断响应[lockInterruptibly()]:
- 方法总结
ReentrantLock重要方法 作用 lock() 获得锁,若锁以及被占用,则等待 lockInterruptibly() 获得锁,但是优先响应中断 tryLock() 尝试获得锁 tryLock(long time, TimeUnit unit) 在time时间内尝试获得锁 unLock() 释放锁
重入锁的搭档:Condition条件
- await() 方法会使当前线程等待,同时释放锁,当其他线程使用signal()或者signalAll()方法时,线程会重新获得锁并重新执行。当线程中断时,也能挑出等待。
- awautUninterruptibly() 方法与await() 方法基本相同,但是并不会在等待过程中响应中断。
- signal() 方法用于唤醒一个在等待中的线程。
- signalAll() 唤醒所有在等待中的线程。
允许多个线程同时访问:Semaphore信号量
- 信号量演示例子
public class SempDemo implements Runnable{ final Semaphore semp = new Semaphore(5); @Override public void run(){ try{ semp.acquire(); Thread.sleep(2000); System.out.println(Thread.currentThread().getId()+":done!"); semp.release(); }catch (InterruptedException e){ e.printStackTrace(); } } public static void main(String[] args) { ExecutorService exec = Executors.newFixedThreadPool(20); final SempDemo demo = new SempDemo(); for(int i=0;i<20;i++){ exec.submit(demo); } } }
- 关键方法
Semaphore方法 方法描述 acquire() 从此信号量获取许可证,阻塞直到可用 acquireUninterruptibly() 同acquire(), 但是不响应中断 release() 释放一个许可证
ReadWriteLock读写锁
- 特点:
- 读-读不互斥;读-读之间不阻塞
- 读-写互斥;读阻塞写,写阻塞读
- 写-写互斥;写-写阻塞
倒计时器:CountDownLatch
- 作用:允许一个或多个线程等待直到其他线程完成的同步辅助
- 使用给定的计数初始化,await方法阻塞,直到由于countDown方法的调用导致当前计数器计数清零,之后所有等待线程被释放
循环栅栏:CyclicBarrier
- 作用:允许一组线程全部等待彼此达到共同屏蔽点的同步辅助,可重复使用
线程阻塞工具类:LockSupport
- 作用:可以在线程内任意位置让线程阻塞
原文地址:https://www.cnblogs.com/YuanJieHe/p/12607836.html
时间: 2024-11-02 13:12:54