并发控制利器Semaphore

简介: 并发控制利器Semaphore

并发控制利器:Semaphore详解与应用

简介

Semaphore 是Java并发编程中的一个重要工具,用于管理对共享资源的访问权限,确保系统资源不会因过度访问而耗尽。形象地说,Semaphore 可以比喻为交通信号灯,它控制着能够同时进入特定区域(如马路)的车辆数(线程数)。当一定数量的车辆(线程)进入后,其余车辆必须等待,直到有车辆离开,空出“车位”(许可证)为止。在编程中,Semaphore 通过协调线程访问,保证公共资源的合理分配。



应用场景

Semaphore 特别适用于有限资源访问控制的场景,例如数据库连接池管理、文件读写控制等。一个典型示例是数据库连接限制:假设你需要从数万个文件中读取数据,并将其保存至数据库,虽然读取操作(IO密集型)可以并行处理,但数据库连接数有限(例如10个)。此时,Semaphore 可以用来控制仅有10个线程能同时获取数据库连接,避免超出连接池容量。

public class SemaphoreTest {
    private static final int THREAD_COUNT = 30;
    private static ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_COUNT);
    private static Semaphore s = new Semaphore(10);

    public static void main(String[] args) {
        for (int i = 0; i < THREAD_COUNT; i++) {
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        s.acquire();
                        System.out.println("Saving data...");
                        s.release();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            });
        }
        threadPool.shutdown();
    }
}

在这个例子中,尽管启用了30个线程,但最多只有10个线程能够同时执行数据库保存操作,通过 Semaphore(10) 初始化,确保了并发访问的线程数不超过10。


其他方法及实现机制

Semaphore 提供了多个方法来帮助管理资源访问:

  • availablePermits():返回当前可用的许可证数量。
  • getQueueLength():返回等待获取许可证的线程数。
  • hasQueuedThreads():检查是否有线程正在等待许可证。
  • reducePermits(int reduction):减少指定数量的许可证,是一个受保护方法。
  • getQueuedThreads():返回所有等待的线程集合,同样是受保护方法。

Semaphore 的内部实现基于AQS(AbstractQueuedSynchronizer),利用了CLH队列来管理等待线程。CLH队列是一种FIFO(先进先出)的线程等待队列,当线程尝试获取许可证失败时,会被封装成节点加入到队列中等待。CLH队列的节点结构包含前驱节点和后继节点的引用,以及线程状态等信息,通过这些信息维护线程的等待顺序。


在尝试获取锁的操作中,AQS的acquire() 方法首先尝试快速获取资源,失败则通过addWaiter()方法将当前线程封装成节点并加入队列。此过程体现了CLH队列的结构和等待机制,确保了线程安全且高效地获取和释放资源。


总之,Semaphore 作为一种灵活的并发控制工具,通过限制并发访问的数量,有效管理共享资源,是解决资源竞争和提高系统并发能力的重要手段。

相关文章
|
8月前
|
Java
Java并发编程中的锁机制
【2月更文挑战第22天】 在Java并发编程中,锁机制是一种重要的同步手段,用于保证多个线程在访问共享资源时的安全性。本文将介绍Java锁机制的基本概念、种类以及使用方法,帮助读者深入理解并发编程中的锁机制。
|
8月前
|
缓存 安全 Java
高性能解决线程饥饿的利器 StampedLock
高性能解决线程饥饿的利器 StampedLock
106 1
|
8月前
|
缓存 安全 Java
Java并发编程中的锁机制及其应用
传统的锁机制在Java并发编程中扮演着重要角色,但随着技术的发展,新的锁机制和应用不断涌现。本文将深入探讨Java并发编程中常用的锁机制,包括synchronized关键字、ReentrantLock、ReadWriteLock等,并结合实际案例分析其应用场景和优劣势。通过本文的阐述,读者将对Java并发编程中的锁机制有更为深入的了解。
74 0
|
4月前
|
Java 数据库
JAVA并发编程-一文看懂全部锁机制
曾几何时,面试官问:java都有哪些锁?小白,一脸无辜:用过的有synchronized,其他不清楚。面试官:回去等通知! 今天我们庖丁解牛说说,各种锁有什么区别、什么场景可以用,通俗直白的分析,让小白再也不怕面试官八股文拷打。
|
8月前
|
算法 安全
AtomicInteger使用非阻塞算法,实现并发控制多线程实现售票
AtomicInteger使用非阻塞算法,实现并发控制多线程实现售票
|
8月前
|
数据库
比读写锁更快的 StampedLock
比读写锁更快的 StampedLock
107 0
|
8月前
|
存储 算法 Java
JUC并发编程之Synchronized锁优化
HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。
105 0
|
8月前
多线程并发锁的方案—互斥锁
多线程并发锁的方案—互斥锁
|
缓存 算法 安全
06.一文看懂并发编程中的锁
大家好,我是王有志。相信你经常会听到读锁/写锁,公平锁/非公平锁,乐观锁/悲观锁等五花八门的锁,那么每种锁有什么用呢?它们又有什么区别呢?今天我们就一起聊聊并发编程中的各种锁。
226 1
06.一文看懂并发编程中的锁
|
Java
并发编程——JUC并发工具
JUC 是Java并发编程工具类库,提供了一些常用的并发工具,例如锁、信号量、计数器、事件循环、线程池、并发集合等。这些工具可以帮助开发人员简化并发编程的复杂性,提高程序效率和可靠性。
61 0