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();
    }

  

 

posted @ 2022-07-15 17:14  XUMT111  阅读(105)  评论(0编辑  收藏  举报