本文共 3389 字,大约阅读时间需要 11 分钟。
Semaphore 是 Java 多线程环境中的一个重要信号量,用于更细粒度地控制线程的并发执行。它比 synchronized 减少了争用锁的概率,实现了更细粒度的资源管理。Semaphore 的核心作用是为线程资源分配提供控制机制,使得多个线程能够有序地执行。
Semaphore 是一种信号量,它使用一个共享锁机制来管理可以被多个线程同时占用的资源。它维护了一个许可集,线程可以通过 acquire() 方法获取令牌,以便获取资源,并在执行完成后调用 release() 方法归还令牌。信号量在没有可用许可的情况下,线程会阻塞等待,直到有线程释放资源。这种机制保证了线程的有序执行和资源的高效利用。
public class SemaphoreDemo { public static void main(String[] args) { Semaphore semaphore = new Semaphore(3); // 创建一个具有3个资源的信号量 for (int i = 0; i < 10; i++) { new Thread(() -> { try { semaphore.acquire(); // 获取资源 System.out.println(Thread.currentThread().getName() + "拿到了令牌,执行中..."); Thread.sleep(1000); semaphore.release(); // 归还资源 } catch (InterruptedException e) { e.printStackTrace(); } }, "Thread" + i).start(); } }}
Thread0拿到了令牌,执行中...2020-07-19 05:52:43Thread2拿到了令牌,执行中...2020-07-19 05:52:43Thread1拿到了令牌,执行中...2020-07-19 05:52:43Thread4拿到了令牌,执行中...2020-07-19 05:52:44Thread5拿到了令牌,执行中...2020-07-19 05:52:44Thread3拿到了令牌,执行中...2020-07-19 05:52:44Thread6拿到了令牌,执行中...2020-07-19 05:52:45Thread7拿到了令牌,执行中...2020-07-19 05:52:45Thread8拿到了令牌,执行中...2020-07-19 05:52:45Thread9拿到了令牌,执行中...2020-07-19 05:52:46
此示例展示了信号量的基本使用场景。一共启动了10个线程请求资源。信号量初始化为3个许可,在前3个线程获取成功后,其他线程需要等待直到有线程释放资源。可见,信号量为线程资源分配合理提供了保障,避免了资源的无序争用和竞态条件。
public class SemaphoreDemo { public static void main(String[] args) { Semaphore semaphore = new Semaphore(2, true); // 允许动态扩容 for (int i = 0; i < 5; i++) { new Thread(() -> { try { if (semaphore.tryAcquire(1)) { System.out.println(Thread.currentThread().getName() + "拿到了令牌,执行中..."); Thread.sleep(1000); semaphore.release(1); } else { System.out.println(Thread.currentThread().getName() + "没有获取到令牌"); } } catch (InterruptedException e) { e.printStackTrace(); } }, "Thread" + i).start(); } }}
Thread0拿到了令牌,执行中...2020-07-19 06:27:17Thread1拿到了令牌,执行中...2020-07-19 06:27:17Thread2没有获取到令牌Thread3没有获取到令牌Thread4没有获取到令牌
该示例展示了信号量的动态许可管理机制。初始时,信号量允许最多2个线程同时获取资源。前两个线程成功获取资源,执行完毕后归还资源,动态地扩容以支持更多线程请求。
SEMAPHORE的构造函数接受两个参数:int permits 和 boolean fairSharing。permits
是声明的最大并发数量。fairSharing
表示一个是否公平分配。
线程通过 acquire()
获取资源,如果没有可用资源,线程会被阻塞。资源释放后,线程能够继续执行。release()
用于归还资源。
Semaphore 的动态扩容功能确保了资源的高效利用。例如,初始化时设置了4个资源,线程每次获取1个,当有线程释放时,系统会自动扩容以满足新的需求。这突破了传统的固定并发度限制,使得资源分配更加灵活。
在多线程应用中,信号量用于控制线程的并发数量。例如,在 Web服务器环境下,信号量可以保障网路连接的处理单例性。
任何可以被多次占用的共享资源都可以用信号量来管理。例如,数据库连接池、文件资源等。
合理使用信号量可以避免死锁和资源泄漏,提升系统性能。例如,在资源收集和连接池管理中,信号量提供了响应式的资源调度机制。
信号量是 Java 多线程应用中的核心机制之一。它通过互斥锁和许可集的管理,为线程间的资源竞争提供了有序的解决方案。在实际应用中,信号量的灵活使用能够显著提升线程的执行效率和系统的整体性能。通过合理配置信号量,开发者能够更好地管理线程的并发执行,避免资源竞争和 deadlock 问题。同时,理解信号量的动态扩容机制,能够使系统在面对突发负载时具备更高的弹性和响应速度。
转载地址:http://guizk.baihongyu.com/