AQS
synchronized
1,获取不到锁-等待 其他线程释放锁(被锁代码执行完或者wait) 本线程参与竞争锁
2,获取到锁 wait(释放锁,其他线程继续竞争) 其他线程通知notifyAll 本线程参与竞争锁 获取锁成功继续执行业务
ReentrantLock
1,相同的ReentrantLock对象,多线程竞争获取锁
2,使用condition来wait挂起线程释放锁 其他线程继续竞争锁 其他线程通过condition.signal()来通知相同condition的线程来获取锁,以此达到分组通知的目的 每个线程传入不通的condition来condition.await()及signal
3,可实现公平锁和非公平锁
4,使用起来更加灵活,lock.lock()获取锁,获取不到-等待,类似synchronize tryLock能获得锁就返回true,不能就立即返回false
5,提供了线程中断机制 lockInterruptibly() interrupt()
AbstractQueuedSynchronizer
1,AQS定义了一套多线程访问共享资源的同步器框架 是一个依赖状态(state)的同步器
维护了一个队列 一个状态值 用CAS算法尝试获取锁(修改状态值) 获取不到锁放入队列
2,
非公平锁:无论CLH队列中是否有节点,当前线程都要和队列头的节点去竞争一下锁;若竞争到锁,则该线程去持有锁;若没有竞争到锁,则放入到CLH队列尾部;
公平锁:无论CLH队列中是否有节点,当前线程都是去放到队列的尾部
3,lock获取锁机制,无限循环+CAS操作竞争锁
当本节点的前一个节点是head时,尝试获取锁 获取成功,设置为head节点
https://www.cnblogs.com/yufeng218/p/13090453.html
通过cas操作放入队尾 Node pred = tail; if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) {//尾部节点的期望值pred,更新值node 多线程竞争,期望值不匹配,继续CAS pred.next = node; return node; } }
AS的全称是Compare-And-Swap,它是CPU并发原语。
原语的执行必须是连续的,在执行过程中不允许被中断,也就是说CAS是一条CPU的原子指令,不会造成所谓的数据不一致的问题,也就是说CAS是线程安全的
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
interrupt() 如果线程被阻塞 可实现中断处理 ① 如果线程处于被阻塞状态(例如处于sleep, wait, join 等状态),那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常。仅此而已。 ② 如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true,仅此而已。被设置中断标志的线程将继续正常运行,不受影响。 @Test public void myTest(){ ServiceTest test = new ServiceTest(); Thread t1 = new Thread(){ @Override public void run(){ try { test.stest(); } catch (Exception e) { System.out.println("*******interrupt:"+Thread.currentThread().getName()); } } }; t1.start(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } t1.interrupt(); } public synchronized void stest() throws Exception { System.out.println("**********stest*******"+Thread.currentThread().getName()); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); throw e; } System.out.println("**********stest-end*******"+Thread.currentThread().getName()); } 针对第二种情况,以下运行结果 false true last:false 线程执行结束后,会变回false System.out.println(t1.isInterrupted()); t1.start(); t1.interrupt(); System.out.println(t1.isInterrupted()); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("last:"+t1.isInterrupted());
ReentrantLock 线程中断 lock.lockInterruptibly(); t1.interrupt(); 获取不到锁 则被中断,中断异常处理逻辑 private Lock lock = new ReentrantLock(); public void doBussiness() { String name = Thread.currentThread().getName(); System.out.println(name + " 开始获取锁"); try { lock.lockInterruptibly(); System.out.println(name + " 得到锁"); Thread.sleep(10000); } catch (InterruptedException e) { System.out.println(name + " 被中断"); } finally { try { lock.unlock(); System.out.println(name + " 释放锁"); } catch (Exception e) { System.out.println(name + " : 没有得到锁的线程运行结束"); } } } public static void main(String[] args) throws InterruptedException { LockTest lockTest = new LockTest(); Thread t0 = new Thread( new Runnable() { @Override public void run() { lockTest.doBussiness(); } } ); Thread t1 = new Thread( new Runnable() { @Override public void run() { lockTest.doBussiness(); } } ); // 启动线程t1 t0.start(); Thread.sleep(10); // 启动线程t2 t1.start(); Thread.sleep(5000); // 线程t1没有得到锁,中断t1的等待 t1.interrupt(); }