0
点赞
收藏
分享

微信扫一扫

Unity环绕物体的摄像机,添加了遮挡的适应

一.什么是AQS?

1.AQS,AbstractQueuedSynchronizer,抽象队列同步器,是一个用于构建锁和同步器的框架。

2.基于AQS实现的锁或同步器有:可重入锁ReentrantLock、计时锁CountDownLatch、信号量Semaphore等

3.AQS三大核心

(1)state:用整型变量state来标记共享变量的状态,多线程通过操作state来实现锁或同步器机制,state需要用volatile修饰。

(2)queue:AQS内部维护一个基于FIFO算法和双向链表实现的队列。若线程请求共享变量失败,则会被包装成一个Node节点,存到队列尾部。当共享变量空闲,则会唤醒队列的第一个线程去操作变量。

(3)CAS:多线程操作state是通过CAS操作完成的。

4.AQS的两种模式:独占锁和共享锁

(1)独占锁:共享变量只能被一个线程获取到。state初值为0,表示无锁状态,线程可以使用;当线程获取到锁,则通过CAS操作对state加1,表示变量被上锁,其他线程不能使用;当state为0时会唤醒队列中的第一个线程。

(2)共享锁:共享变量可以被多个线程获取到。state初值为N,表示可以被N个线程使用;当线程获取到锁,则通过CAS操作对state减1;当state为0时,其他线程陷入阻塞;当有一个线程释放锁,就会唤醒队列中的第一个线程。

二.synchronized和Lock的区别

1.语法层面

(1)synchronized是关键字,源码在jvm中,由c++实现

(2)Lock是jdk提供的一个接口,由java实现

2.释放锁的方式

(1)synchronized在执行完代码块或者执行发生异常时,会自动释放锁

(2)Lock在执行完代码或者执行发生异常时,都不会主动释放锁,必须调用unlock()手动释放锁

3.功能层面

synchronized和Lock都属于悲观锁,实现了锁机制基本的互斥、同步、锁重入功能;但Lock锁又具有额外的功能

(1)公平锁:可以选择将锁设置为公平锁,即线程按照等待顺序依次获取锁。而synchronized是所有线程一同争抢锁。

(2)可打断:如果线程尝试用lockInterrupibly()获取锁,则线程在等待锁的过程中可以调用interrupt()打断。而synchronized如果在线程等待锁的过程中调用interrupt()打断,会抛出异常。

(3)计时等待:线程使用tryLock()方法获取锁

        a.tryLock()是一个非阻塞方法,如果线程获取到锁,则返回true;如果线程获取不到锁,则直接返回false,不会阻塞等待。

        b.tryLock(long time,TimeUnit unit)用于计时等待,如果线程获取到锁,则返回true;如果线程获取不到锁,会进入计时等待;若在等待时间内获取到锁,则返回true;若超时仍获取不到锁,则返回false。

        c.通过tryLock()方式获取锁,既能知道线程是否获取到锁,还能避免线程陷入长时间阻塞。而synchronized会永久阻塞获取不到锁的线程,且无法知道当前线程是否获取到锁。

(4)多条件等待:可以通过Lock提供的newCondition()方法创建多个条件;线程在获取到锁后,可以通过调用Condition()的await()方法进入等待状态,此时会释放锁;其他线程在获取到锁后,可以通过调用Condition()的signal()方法唤醒因当前条件而进入等待的线程。Lock可以创建多个Condition,对不同线程进行灵活地等待与唤醒。而synchronized只能通过唯一的锁对象来关联等待与唤醒线程。

三.ReentrantLock的实现原理

1.ReentrantLock是支持重入的独占锁,基于AQS框架和Lock接口实现。

2.ReentrantLock提供了公平锁和非公平锁两种模式:公平锁模式下,所有线程会按照等待的先后顺序依次获取锁;非公平锁模式下,对于新进入的线程,会直接通过CAS操作尝试获取锁,CAS操作失败才进入队尾排队。

3.当一个线程想要获取锁:

(1)通过CAS操作修改锁的状态值state,如果操作成功则获取锁

(2)如果CAS操作失败,说明锁被其他线程持有,当前线程进入等待

4.当一个线程想要释放锁:

(1)通过CAS操作修改锁的状态值state

(2)唤醒队列的第一个线程

(3)将该线程从队列移除

5.ReentrantLock支持可重入的特性,即同一线程可以多次获取锁而不陷入阻塞。线程每重入一次锁,就通过CAS对state加1;每释放一次锁就通过CAS对state减1。只有当state为0时才唤醒下一个线程。

举报

相关推荐

0 条评论