长宁区网站建设网页制,安徽省建设工程信息网安徽省政务,软件工程考研学校排名,做设计的有什么网站文章目录什么是AQSAbstractQueuedSynchronizer方法解析自旋与阻塞ReentrantLock#xff0c;Semaphore以及CountDownLatch对比ReentrantLock实现原理原理ReentrantLock源码中compareAndSetState的方法Semaphore实现原理CountDownLatch实现原理什么是AQS
AQS是Java中的一个抽象…
文章目录什么是AQSAbstractQueuedSynchronizer方法解析自旋与阻塞ReentrantLockSemaphore以及CountDownLatch对比ReentrantLock实现原理原理ReentrantLock源码中compareAndSetState的方法Semaphore实现原理CountDownLatch实现原理什么是AQS
AQS是Java中的一个抽象队列同步器AbstractQueuedSynchronizer类它提供了一种实现同步器的框架和实现方式。它是Java并发编程中的一个重要组成部分广泛用于实现ReentrantLock、Semaphore、CountDownLatch等同步工具类。
AQS的核心思想是利用一个先进先出FIFO的双向队列来管理线程的竞争和等待。AQS提供了两种模式独占模式和共享模式。独占模式是指只有一个线程可以持有同步状态如ReentrantLock共享模式是指多个线程可以同时持有同步状态如Semaphore。
AQS的具体实现方式是通过维护一个volatile变量state表示同步状态当state为0时表示没有线程占用同步状态当state为1时表示有一个线程占用同步状态。当多个线程竞争同步状态时只有一个线程可以成功占用同步状态其余线程将加入到AQS的同步队列中等待。当占用同步状态的线程释放同步状态时AQS会从同步队列中选择一个线程唤醒使其重新尝试获取同步状态。
总之AQS提供了一种高效且灵活的实现同步器的方式可以满足不同的并发编程需求。
AbstractQueuedSynchronizer方法解析
AbstractQueuedSynchronizerAQS是Java并发编程中的一个基础框架它提供了一种实现同步器的通用方法。AQS内部维护了一个同步队列通过“自旋”和“阻塞”两种方式来实现同步操作。
AQS提供了一些核心方法其含义和作用如下 acquire(int arg): 尝试获取同步状态如果获取失败则加入同步队列并阻塞等待唤醒直到获取同步状态成功。参数arg表示获取同步状态所需的资源数量。 tryAcquire(int arg): 尝试获取同步状态如果获取成功则返回true否则返回false。参数arg表示获取同步状态所需的资源数量。 release(int arg): 释放同步状态通知其他线程可以尝试获取同步状态。参数arg表示释放的资源数量。 tryRelease(int arg): 尝试释放同步状态如果释放成功则返回true否则返回false。参数arg表示释放的资源数量。 acquireInterruptibly(int arg): 尝试获取同步状态如果获取失败则加入同步队列并阻塞等待唤醒直到获取同步状态成功或者被中断。参数arg表示获取同步状态所需的资源数量。 acquireShared(int arg): 尝试获取共享同步状态如果获取失败则加入同步队列并阻塞等待唤醒直到获取共享同步状态成功。参数arg表示获取共享同步状态所需的资源数量。 tryAcquireShared(int arg): 尝试获取共享同步状态如果获取成功则返回非负数否则返回负数。返回值表示当前线程获取到的共享资源数量。参数arg表示获取共享同步状态所需的资源数量。 releaseShared(int arg): 释放共享同步状态通知其他线程可以尝试获取共享同步状态。参数arg表示释放的资源数量。 tryAcquireNanos(int arg, long nanosTimeout): 在规定时间内尝试获取同步状态如果获取失败则加入同步队列并阻塞等待唤醒直到获取同步状态成功或者超时。参数arg表示获取同步状态所需的资源数量参数nanosTimeout表示等待超时时间。
AQS提供了一些核心方法来实现同步操作可以用于实现不同类型的同步器如ReentrantLock、Semaphore、CountDownLatch等。这些方法可以满足不同的并发编程需求需要根据具体的场景选择合适的同步方式和同步策略。
自旋与阻塞
自旋和阻塞是Java并发编程中两种不同的线程等待方式。
自旋是指线程在等待某个条件满足时不断地循环检查条件是否满足如果不满足就一直循环等待直到条件满足。自旋的好处是可以减少线程上下文切换的开销因为线程一直处于执行状态不需要进行线程状态的切换。但是自旋需要占用CPU资源如果自旋时间过长会导致CPU资源浪费降低系统性能。
阻塞是指线程在等待某个条件满足时将自己挂起不再占用CPU资源直到条件满足时再被唤醒继续执行。阻塞的好处是可以释放CPU资源避免浪费但是阻塞需要进行线程状态的切换如果线程频繁地阻塞和唤醒会增加系统开销。
在Java中阻塞通常是通过调用wait()方法或者阻塞式IO来实现的而自旋通常是在锁等待时实现的。例如在ReentrantLock中当线程尝试获取锁失败时它会在同步队列中自旋等待锁的释放直到锁被释放或者等待时间超过一定阈值才会阻塞等待。因此在选择线程等待方式时需要根据具体的场景和需求进行权衡和选择
ReentrantLockSemaphore以及CountDownLatch对比
ReentrantLock、Semaphore和CountDownLatch都是Java并发编程中常用的同步工具类它们都使用了AQS的实现方式。
ReentrantLock可重入锁是一种独占锁它允许一个线程多次获取锁支持公平锁和非公平锁。与synchronized关键字相比ReentrantLock提供了更多的灵活性和功能如可中断锁、限时锁、公平锁等。
Semaphore信号量是一种共享锁它用于控制对资源的访问数量。Semaphore维护了一个计数器当有线程获取信号量时计数器减1当计数器为0时其他线程需要等待。Semaphore可以用于实现限流、资源池等功能。
CountDownLatch倒计时器是一种同步工具类它可以让一个或多个线程等待其他线程执行完毕后再继续执行。CountDownLatch维护了一个计数器当计数器为0时等待的线程可以继续执行。它可以用于协调多个线程的执行顺序。
总之ReentrantLock、Semaphore和CountDownLatch都是Java并发编程中非常有用的同步工具类可以帮助我们更好地控制多线程的并发访问和协调多线程的执行。在使用这些工具类时需要注意线程安全和性能问题以及选择合适的同步策略。
ReentrantLock实现原理
原理
获取锁当一个线程请求获取锁时ReentrantLock会首先尝试获取锁如果锁未被占用则该线程可以立即获取锁否则该线程将被加入到同步队列中等待获取锁。
可重入性如果当前线程已经持有锁那么它可以重复获取该锁而不需要重新等待。为了实现可重入性ReentrantLock需要维护一个记录锁持有者的ThreadLocal变量以及一个记录锁持有次数的计数器。
公平性和非公平性ReentrantLock支持公平锁和非公平锁。公平锁是指多个线程获取锁的顺序与它们加入同步队列的顺序相同非公平锁则不保证获取锁的顺序与加入队列的顺序相同。在公平锁模式下线程获取锁的顺序是有序的但是会降低并发性能在非公平锁模式下线程获取锁的顺序是不确定的但是可以提高并发性能。
释放锁当一个线程释放锁时ReentrantLock会将state变量置为0以表示该锁已经被释放。同时它会从同步队列中选择一个等待的线程唤醒使其重新尝试获取锁。如果当前线程还持有该锁那么需要将计数器减1直到计数器为0才能完全释放锁。
ReentrantLock源码中compareAndSetState的方法
在ReentrantLock的源码中比较并交换CompareAndSet状态值是实现锁的核心部分之一。在ReentrantLock中状态值的改变可以表示锁的获取和释放因此状态值的比较并交换是实现锁的关键。
在ReentrantLock中状态值是由AQSAbstractQueuedSynchronizer的内部类Node中的state字段表示的。具体来说当线程获取锁时它会创建一个Node节点并尝试将状态值从0表示锁未被占用改变为1表示锁已被占用。当线程释放锁时它会将状态值从1改变为0表示锁已被释放。
在AQS中compareAndSetState(int expect, int update)方法用于比较并交换状态值。具体来说该方法会比较当前状态值是否等于expect如果是则将状态值修改为update否则不进行修改。这个方法是原子的可以保证状态值的改变是线程安全的。在ReentrantLock中使用compareAndSetState方法实现锁的获取和释放比如在获取锁时将状态值从0修改为1在释放锁时将状态值从1修改为0。
下面是ReentrantLock源码中compareAndSetState方法的具体实现
protected final boolean compareAndSetState(int expect, int update) {return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
该方法调用了unsafe类的compareAndSwapInt方法该方法是一个本地方法用于实现原子的比较并交换操作。其中this表示当前对象stateOffset表示state字段在对象中的偏移量expect表示期望的状态值update表示要修改的状态值。如果当前状态值等于expect则将状态值修改为update并返回true否则返回false。
总之ReentrantLock中的compareAndSetState方法实现了状态值的原子性修改是实现锁的关键部分之一。
Semaphore实现原理
Semaphore是一个计数信号量它可以用于控制同时访问某个资源的线程数量。Semaphore内部维护了一个计数器表示可以访问资源的线程数量线程在访问资源时需要先获取Semaphore的许可当计数器的值大于0时线程可以获取许可并访问资源计数器的值减一当计数器的值为0时线程需要等待其他线程释放许可才能获取许可并访问资源。
Semaphore的实现原理主要是基于AQSAbstractQueuedSynchronizer类Semaphore通过AQS实现了许可的获取和释放并且保证了线程之间的互斥和同步。
Semaphore的实现可以分为两个部分获取许可和释放许可。
获取许可 Semaphore的acquire方法用于获取许可如果当前有可用的许可则获取成功如果没有则线程会被阻塞等待。acquire方法的具体实现如下
public void acquire() throws InterruptedException {sync.acquireSharedInterruptibly(1);
}acquire方法内部调用了AQS的acquireSharedInterruptibly方法该方法实现了阻塞等待。如果当前计数器的值大于0线程可以获取许可并将计数器的值减一如果计数器的值为0则线程会被阻塞等待其他线程释放许可。在AQS中线程的阻塞等待是通过将线程添加到同步队列中实现的。
释放许可 Semaphore的release方法用于释放许可如果当前没有线程等待许可则将许可的数量加一如果有线程等待许可则唤醒一个等待线程并将许可的数量加一。release方法的具体实现如下
public void release() {sync.releaseShared(1);
}release方法内部调用了AQS的releaseShared方法该方法实现了许可的释放和等待线程的唤醒。如果当前有等待线程则会从同步队列中唤醒一个线程让其获取许可并执行如果当前没有等待线程则将许可的数量加一。
Semaphore是基于AQS实现的一个计数信号量通过计数器实现了对许可的控制并通过同步队列实现了线程之间的同步和互斥。Semaphore的实现为线程的访问资源提供了一个简单而可靠的机制。
CountDownLatch实现原理
CountDownLatch是一种同步工具它可以让某个线程一直等待直到其他所有线程都执行完毕。CountDownLatch内部维护了一个计数器线程在执行完毕后调用CountDownLatch的countDown方法将计数器的值减一等待线程调用await方法等待计数器的值变为0当计数器的值变为0时等待线程继续执行。
CountDownLatch的实现原理主要是基于AQSAbstractQueuedSynchronizer类CountDownLatch通过AQS实现了计数器的减少和等待并且保证了线程之间的互斥和同步。
CountDownLatch的实现可以分为两个部分计数器的减少和等待计数器变为0。
计数器的减少 CountDownLatch的countDown方法用于减少计数器的值该方法会将计数器的值减一并唤醒正在等待的线程。countDown方法的具体实现如下
public void countDown() {sync.releaseShared(1);
}countDown方法内部调用了AQS的releaseShared方法该方法实现了许可的释放和等待线程的唤醒。如果当前有等待线程则会从同步队列中唤醒一个线程让其执行如果当前没有等待线程则将许可的数量加一。
等待计数器变为0 CountDownLatch的await方法用于等待计数器的值变为0如果当前计数器的值不为0则等待线程会被阻塞等待。await方法的具体实现如下
public void await() throws InterruptedException {sync.acquireSharedInterruptibly(1);
}await方法内部调用了AQS的acquireSharedInterruptibly方法该方法实现了阻塞等待。如果当前计数器的值为0线程可以直接继续执行如果计数器的值不为0则线程会被阻塞等待其他线程调用countDown方法将计数器的值减少。
总之CountDownLatch是基于AQS实现的一个同步工具通过计数器实现了对线程的控制并通过同步队列实现了线程之间的同步和互斥。CountDownLatch的实现为多个线程之间的同步提供了一个简单而可靠的机制。