Java 标准库 API 系列之 Semaphore

Semaphore是一种经典的同步工具,用于控制并发线程数,它可以保证在同一时间内只有一定数量的线程能够访问某个资源,从而避免线程间的竞争和冲突。

Semaphore有两个核心概念:

  1. 许可证(Permit):表示可用的访问权限数量,Semaphore内部维护了一个许可证池,初始时可以设置许可证的数量。
  2. 信号量(Semaphore):表示一个计数器,当线程想要访问某个资源时,必须先从Semaphore中获取一个许可证,然后才能访问资源;当线程使用完资源后,必须释放许可证,以便其他线程可以访问资源。

Semaphore的使用方式如下:

  1. 创建Semaphore对象,指定许可证数量。
  2. 在需要访问共享资源的线程中,调用acquire()方法获取许可证。
  3. 线程使用共享资源。
  4. 在共享资源使用完毕后,调用release()方法释放许可证。

听起来有点像操作系统里面信号量的概念,其实本质是一样的,不过操作系统层面的信号量是作用于进程与进程之间的同步,java里面的信号量是线程与线程之间的同步。

下面是一个简单的示例代码,使用Semaphore控制了同时执行的线程数目:

import java.util.concurrent.Semaphore;

public class SemaphoreExample {
    public static void main(String[] args) throws InterruptedException {
        Semaphore semaphore = new Semaphore(3); // 许可证数量为3

        // 创建10个线程
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire(); // 获取许可证
                    System.out.println(Thread.currentThread().getName() + " acquire semaphore");
                    Thread.sleep(2000); // 模拟使用共享资源的时间
                    semaphore.release(); // 释放许可证
                    System.out.println(Thread.currentThread().getName() + " release semaphore");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

在上面的示例中,创建了10个线程,但是许可证数量只有3个,因此同时最多只能有3个线程获取许可证,其他线程需要等待。每个线程获取到许可证后,会打印一条日志,表示成功获取许可证,然后等待2秒,模拟使用共享资源的时间,使用完资源后,会打印一条日志,表示成功释放许可证。

总之,Semaphore是一种非常常用的同步工具,可以用于控制并发线程数,防止线程间的竞争和冲突,它的使用方式简单明了,非常适合于多线程编程。

它和锁的区别呢

Semaphore和锁(比如ReentrantLock)的区别在于,锁通常只允许一个线程同时访问共享资源,而Semaphore可以控制同时访问共享资源的线程数量,即可以允许多个线程同时访问。

另外,Semaphore的许可证数量是可以动态调整的,而锁的访问数量是固定的。Semaphore可以用于实现资源池等场景,而锁则更适用于互斥访问共享资源的场景。

使用场景

Semaphore的主要应用场景是控制并发访问某些共享资源的线程数量,通常用于限流和保护资源。

例如,假设有一个公共资源,比如数据库连接池、线程池等,由于该资源的数量是有限的,为了防止过多的线程同时访问该资源导致资源竞争和性能下降,可以使用Semaphore来控制并发线程的数量。另外,Semaphore也可以用于限制并发请求的数量,避免服务器过载。

另外,Semaphore还可以用于实现生产者-消费者模型,其中生产者和消费者之间需要进行同步和协作,以避免出现数据竞争或者生产者和消费者之间的阻塞情况。Semaphore可以用来控制生产者和消费者的访问数量,以保证生产者和消费者之间的同步和协作。