Skip to content

Commit 07b18f8

Browse files
committed
Update 2020最新Java并发进阶常见面试题总结.md
1 parent 5fdb3f8 commit 07b18f8

File tree

1 file changed

+5
-5
lines changed

1 file changed

+5
-5
lines changed

docs/java/multi-thread/2020最新Java并发进阶常见面试题总结.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -968,20 +968,20 @@ protected final boolean compareAndSetState(int expect, int update) {
968968

969969
**AQS 定义两种资源共享方式**
970970

971-
- **Exclusive**(独占):只有一个线程能执行,如 ReentrantLock。又可分为公平锁和非公平锁:
971+
- **Exclusive**(独占):只有一个线程能执行,如 `ReentrantLock`。又可分为公平锁和非公平锁:
972972
- 公平锁:按照线程在队列中的排队顺序,先到者先拿到锁
973973
- 非公平锁:当线程要获取锁时,无视队列顺序直接去抢锁,谁抢到就是谁的
974-
- **Share**(共享):多个线程可同时执行,如 Semaphore/CountDownLatchSemaphoreCountDownLatchCyclicBarrierReadWriteLock 我们都会在后面讲到。
974+
- **Share**(共享):多个线程可同时执行,如` CountDownLatch``Semaphore``CountDownLatch``CyclicBarrier``ReadWriteLock` 我们都会在后面讲到。
975975

976-
ReentrantReadWriteLock 可以看成是组合式,因为 ReentrantReadWriteLock 也就是读写锁允许多个线程同时对某一资源进行读。
976+
`ReentrantReadWriteLock` 可以看成是组合式,因为 `ReentrantReadWriteLock` 也就是读写锁允许多个线程同时对某一资源进行读。
977977

978978
不同的自定义同步器争用共享资源的方式也不同。自定义同步器在实现时只需要实现共享资源 state 的获取与释放方式即可,至于具体线程等待队列的维护(如获取资源失败入队/唤醒出队等),AQS 已经在顶层实现好了。
979979

980980
#### 6.2.3. AQS 底层使用了模板方法模式
981981

982982
同步器的设计是基于模板方法模式的,如果需要自定义同步器一般的方式是这样(模板方法模式很经典的一个应用):
983983

984-
1. 使用者继承 AbstractQueuedSynchronizer 并重写指定的方法。(这些重写方法很简单,无非是对于共享资源 state 的获取和释放)
984+
1. 使用者继承 `AbstractQueuedSynchronizer` 并重写指定的方法。(这些重写方法很简单,无非是对于共享资源 state 的获取和释放)
985985
2. 将 AQS 组合在自定义同步组件的实现中,并调用其模板方法,而这些模板方法会调用使用者重写的方法。
986986

987987
这和我们以往通过实现接口的方式有很大区别,这是模板方法模式很经典的一个运用。
@@ -1001,7 +1001,7 @@ tryReleaseShared(int)//共享方式。尝试释放资源,成功则返回true
10011001

10021002
以 ReentrantLock 为例,state 初始化为 0,表示未锁定状态。A 线程 lock()时,会调用 tryAcquire()独占该锁并将 state+1。此后,其他线程再 tryAcquire()时就会失败,直到 A 线程 unlock()到 state=0(即释放锁)为止,其它线程才有机会获取该锁。当然,释放锁之前,A 线程自己是可以重复获取此锁的(state 会累加),这就是可重入的概念。但要注意,获取多少次就要释放多么次,这样才能保证 state 是能回到零态的。
10031003

1004-
再以 CountDownLatch 以例,任务分为 N 个子线程去执行,state 也初始化为 N(注意 N 要与线程个数一致)。这 N 个子线程是并行执行的,每个子线程执行完后 countDown()一次,state 会 CAS(Compare and Swap)减 1。等到所有子线程都执行完后(即 state=0),会 unpark()主调用线程,然后主调用线程就会从 await()函数返回,继续后余动作。
1004+
再以 `CountDownLatch` 以例,任务分为 N 个子线程去执行,state 也初始化为 N(注意 N 要与线程个数一致)。这 N 个子线程是并行执行的,每个子线程执行完后` countDown()` 一次,state 会 CAS(Compare and Swap)减 1。等到所有子线程都执行完后(即 state=0),会 unpark()主调用线程,然后主调用线程就会从 `await()` 函数返回,继续后余动作。
10051005

10061006
一般来说,自定义同步器要么是独占方法,要么是共享方式,他们也只需实现`tryAcquire-tryRelease``tryAcquireShared-tryReleaseShared`中的一种即可。但 AQS 也支持自定义同步器同时实现独占和共享两种方式,如`ReentrantReadWriteLock`
10071007

0 commit comments

Comments
 (0)