JUC工具类: Semaphore详解

简介: 信号量Semaphore是并发编程中的一种高级同步机制,它可以在复杂的资源共享场景中发挥重要作用。理解它的工作原理及正确的使用方法对实现高效且健壮的并发控制至关重要。

在并发编程中,Semaphore(信号量)是一种重要的同步辅助类,用于控制对共享资源的访问。它是java.util.concurrent(JUC)包提供的工具之一,在Java语言中被广泛应用。Semaphore的核心思想是维护一组许可证,它可以控制同时访问特定资源的线程数量。

Semaphore的工作原理

Semaphore管理一系列许可证(permits),线程可以通过 acquire()方法来获取许可证,如果Semaphore持有足够的许可证,则允许线程的执行,如果没有,则线程需要等待,直到有线程释放许可证。线程执行完毕后,应调用 release()方法来释放许可证,以供其他线程使用。

Semaphore的主要方法

  • acquire(): 请求一个许可证。如果许可证不可用,当前线程将被阻塞,直到有许可证被释放。
  • acquire(int permits): 请求给定数量的许可证。
  • release(): 释放一个许可证,将其返回给Semaphore。
  • release(int permits): 释放多个许可证。
  • tryAcquire(): 尝试获取一个许可证,如果没有可用的许可证,立即返回false。
  • tryAcquire(long timeout, TimeUnit unit): 尝试在给定时间内获取许可证,如果在指定的时间内没有获取到,返回false。

Semaphore的应用场景

Semaphore常被用于资源池(如数据库连接池、线程池)的管理,保证有限的资源被合理地分配。它也可以用来实现某些特殊的同步需求,比如限流,即限制某段时间内的访问量。

一个简单的Semaphore示例

下面举例说明如何使用Semaphore来控制对资源的访问:

import java.util.concurrent.Semaphore;

public class SemaphoreExample {

    // 创建Semaphore实例并指定许可证数量为5
    private static final Semaphore semaphore = new Semaphore(5);

    public static void main(String[] args) {
        // 模拟有10个线程同时请求访问资源
        for (int i = 0; i < 10; i++) {
            new Thread(new Worker(i)).start();
        }
    }

    static class Worker implements Runnable {
        private int num;

        public Worker(int num) {
            this.num = num;
        }

        @Override
        public void run() {
            try {
                // 请求许可证
                semaphore.acquire();
                System.out.println("线程" + num + "获取许可证,当前可用许可证数量:" + semaphore.availablePermits());

                // 模拟业务操作,线程睡眠2秒
                Thread.sleep(2000);

                // 释放许可证
                semaphore.release();
                System.out.println("线程" + num + "释放许可证,当前可用许可证数量:" + semaphore.availablePermits());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在这个示例中,我们定义了一个Semaphore,它持有5个许可证。然后,启动了10个线程要求访问共享资源。当一个线程开始运行时,它会尝试通过 acquire()方法从Semaphore获取许可证,如果获取到许可证,线程将执行,并在完成后释放许可证。如果许可证全部被其他线程持有,后来的线程将被阻塞,直到有许可证释放。

注意事项和最佳实践

  1. 确保资源的使用量不会超过Semaphore允许的许可证数目。
  2. 经典的错误是忘记释放许可证,这将导致其他线程无法访问资源。
  3. 尽量使用 tryAcquire带有超时的重载版本,避免永久等待资源的情况发生。
  4. 在使用Semaphore时,建议在 finally代码块中释放许可证,确保许可证总能被释放。
  5. Semaphore不跟踪哪个线程获取了许可证,因此任何线程都可以释放许可证,这点在设计同步策略时需要注意。

信号量Semaphore是并发编程中的一种高级同步机制,它可以在复杂的资源共享场景中发挥重要作用。理解它的工作原理及正确的使用方法对实现高效且健壮的并发控制至关重要。

目录
相关文章
|
6月前
|
安全 Java API
JavaEE初阶 CAS,JUC的一些简单理解,包含concurrent, ReentrantLock,Semaphore以及ConcurrentHashMap
JavaEE初阶 CAS,JUC的一些简单理解,包含concurrent, ReentrantLock,Semaphore以及ConcurrentHashMap
47 0
|
消息中间件 监控 Java
JUC第二十六讲:JUC工具类: CountDownLatch详解
JUC第二十六讲:JUC工具类: CountDownLatch详解
|
3月前
|
Java
JUC工具类: CountDownLatch详解
`CountDownLatch`是并发编程实践中的一个重要工具,它能简化多线程协调执行的复杂性,特别是在当一个操作需要等待一个或多个事件完成才能继续执行时。使用 `CountDownLatch`可以编写简洁的并行代码,确保在执行操作之前,所有的必要步骤都已经准备就绪。
27 1
|
2月前
|
并行计算 Java 开发者
JUC工具类: CyclicBarrier详解
`CyclicBarrier`是并发编程领域一个非常实用的同步辅助类,适用于并行任务场景,它提供了一种简便的线程同步机制。正确地理解和使用这个工具,对开发者来说,可以大大简化并行处理逻辑的复杂度,增强代码的健壮性与可维护性。
17 0
|
5月前
|
Java 数据库
深入解析Java并发包(JUC)中的Semaphore
深入解析Java并发包(JUC)中的Semaphore
|
存储 安全 算法
一天一个 JUC 工具类 -- 并发集合
使用JUC工具包中的并发集合,我们可以避免手动处理锁和同步的复杂性,从而降低出现线程安全问题的概率。这些并发集合通过内部采用高效的算法和数据结构来优化并发操作,从而提供更好的性能和扩展性。
|
6月前
|
Java
JUC 常用 4 大并发工具类 CountDownLatch、CyclicBarrier、Semaphore、ExChanger
JUC 常用 4 大并发工具类 CountDownLatch、CyclicBarrier、Semaphore、ExChanger
JUC第二十八讲:JUC工具类: Semaphore详解
JUC第二十八讲:JUC工具类: Semaphore详解
JUC第二十七讲:JUC工具类: CyclicBarrier详解
JUC第二十七讲:JUC工具类: CyclicBarrier详解
|
存储 安全 Java
一天一个 JUC 工具类 -- AQS
AbstractQueuedSynchronizer(AQS)是Java中用于构建锁和同步器的抽象基类。它是Java并发工具包(java.util.concurrent)中实现高级线程同步控制的关键组件之一。AQS提供了一种基于等待队列的同步器框架,允许开发者构建自定义的同步器。在这篇文章中我们将从源码分析和底层原理的角度来介绍AQS。