Java信号量(Semaphore)
引言
在并发编程中,为了控制多个线程对共享资源的访问,我们需要使用一些同步机制。Java提供了多种同步机制,其中之一就是信号量(Semaphore)。信号量是一种计数器,用来控制能同时访问共享资源的线程数量。本文将详细介绍Java中信号量的概念、用法和示例代码。
什么是信号量?
信号量是一种同步工具,用于保护共享资源。它维护了一个计数器,可以用来控制对共享资源的访问。信号量有两种类型:计数信号量和二进制信号量。
- 计数信号量:可以控制多个线程同时访问共享资源的数量;
- 二进制信号量:只能允许一个线程访问共享资源。
Java中的信号量
Java中的信号量是通过java.util.concurrent.Semaphore
类实现的。它提供了以下常用方法:
acquire()
:获取一个许可,如果没有可用的许可,则阻塞等待;release()
:释放一个许可;tryAcquire()
:尝试获取一个许可,如果成功则返回true
,否则返回false
;tryAcquire(long timeout, TimeUnit unit)
:在指定的时间内尝试获取一个许可,如果成功则返回true
,否则返回false
。
我们可以使用信号量来控制同时访问某个共享资源的线程数量。当一个线程需要访问共享资源时,它必须先通过acquire()
方法获取一个许可。如果许可数量已经达到上限,线程将被阻塞,直到有其他线程释放许可。使用完共享资源后,线程需要通过release()
方法释放占用的许可。
示例代码
以下是一个使用信号量的示例代码,模拟了10个线程同时访问一个共享资源的场景。共享资源的访问被限制为同时只能有3个线程进行。
import java.util.concurrent.Semaphore;
public class SharedResource {
private static Semaphore semaphore = new Semaphore(3);
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new Worker(i));
thread.start();
}
}
static class Worker implements Runnable {
private int id;
public Worker(int id) {
this.id = id;
}
@Override
public void run() {
try {
semaphore.acquire(); // 获取许可
System.out.println("Thread " + id + " is accessing the shared resource.");
Thread.sleep(2000); // 模拟访问共享资源的耗时操作
System.out.println("Thread " + id + " has finished accessing the shared resource.");
semaphore.release(); // 释放许可
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
在上述代码中,我们创建了一个Semaphore
对象,并指定了许可数量为3。然后,我们创建了10个线程,每个线程都会尝试获取一个许可,并对共享资源进行访问。当有3个线程获得许可时,其他线程将被阻塞,直到有线程释放许可。
以下是代码运行的示例输出:
Thread 1 is accessing the shared resource.
Thread 2 is accessing the shared resource.
Thread 0 is accessing the shared resource.
Thread 2 has finished accessing the shared resource.
Thread 1 has finished accessing the shared resource.
Thread 0 has finished accessing the shared resource.
Thread 3 is accessing the shared resource.
Thread 4 is accessing the shared resource.
Thread 3 has finished accessing the shared resource.
Thread 5 is accessing the shared resource.
Thread 4 has finished accessing the shared resource.
Thread 6 is accessing the shared resource.
Thread 5 has finished accessing the shared resource.
Thread 6 has finished accessing the shared resource.
Thread 7 is accessing the shared resource.
Thread 8 is accessing the shared resource.
Thread 9 is accessing the shared resource.
Thread 7 has finished accessing the shared resource.
Thread 8 has finished accessing the shared resource.
Thread 9 has finished accessing the shared resource.
如上所示,同时只