Java中的Semaphore:控制共享资源访问的工具

Java Q&A Hub 使用 GPT-4o-mini 回答

问题:

Java面试题之多线程 Java中Semaphore是什么?

回答:

在Java中,Semaphore 是一个用于控制对共享资源访问的计数信号量。它是 java.util.concurrent 包中的一个类,主要用于实现对资源的并发访问控制。Semaphore 可以用来限制同时访问某个特定资源的线程数量,从而避免资源的过度使用或竞争。

Semaphore的基本概念

  • 计数信号量Semaphore 维护一个计数器,表示可用的许可证数量。线程在访问共享资源之前需要获取一个许可证,访问完成后需要释放许可证。
  • 许可证:每个线程在访问共享资源时需要获取一个许可证,许可证的数量由信号量的初始值决定。
  • 公平性Semaphore 可以是公平的或不公平的。公平的信号量会按照线程请求的顺序来分配许可证,而不公平的信号量则可能会让某些线程优先获取许可证。

Semaphore的常用方法

  • acquire(): 获取一个许可证,如果没有可用的许可证,线程会被阻塞,直到有许可证可用。
  • release(): 释放一个许可证,增加可用许可证的数量。
  • availablePermits(): 返回当前可用的许可证数量。
  • tryAcquire(): 尝试获取一个许可证,如果成功则返回 true,否则返回 false,不会阻塞线程。

示例代码

以下是一个使用 Semaphore 的简单示例:

import java.util.concurrent.Semaphore;

public class SemaphoreExample {
    private static final Semaphore semaphore = new Semaphore(2); // 允许最多2个线程同时访问

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            new Thread(new Task(i)).start();
        }
    }

    static class Task implements Runnable {
        private int id;

        public Task(int id) {
            this.id = id;
        }

        @Override
        public void run() {
            try {
                System.out.println("Thread " + id + " is trying to acquire a permit.");
                semaphore.acquire(); // 获取许可证
                System.out.println("Thread " + id + " has acquired a permit.");

                // 模拟访问共享资源
                Thread.sleep(2000);

                System.out.println("Thread " + id + " is releasing the permit.");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                semaphore.release(); // 释放许可证
                System.out.println("Thread " + id + " has released the permit.");
            }
        }
    }
}

总结

Semaphore 是一个强大的工具,可以帮助开发者控制对共享资源的访问,避免资源竞争和过度使用。在多线程编程中,合理使用 Semaphore 可以提高程序的稳定性和性能。