博客
关于我
Java并发编程之Semaphore
阅读量:761 次
发布时间:2019-03-23

本文共 3389 字,大约阅读时间需要 11 分钟。

Semaphore (信号量)详解

Semaphore 是 Java 多线程环境中的一个重要信号量,用于更细粒度地控制线程的并发执行。它比 synchronized 减少了争用锁的概率,实现了更细粒度的资源管理。Semaphore 的核心作用是为线程资源分配提供控制机制,使得多个线程能够有序地执行。

1. 概念

Semaphore 是一种信号量,它使用一个共享锁机制来管理可以被多个线程同时占用的资源。它维护了一个许可集,线程可以通过 acquire() 方法获取令牌,以便获取资源,并在执行完成后调用 release() 方法归还令牌。信号量在没有可用许可的情况下,线程会阻塞等待,直到有线程释放资源。这种机制保证了线程的有序执行和资源的高效利用。

2. 示例

示例一:基础使用示例

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个线程同时获取资源。前两个线程成功获取资源,执行完毕后归还资源,动态地扩容以支持更多线程请求。

3. 说明

1. creatingSemaphore

SEMAPHORE的构造函数接受两个参数:int permits 和 boolean fairSharing。permits 是声明的最大并发数量。fairSharing 表示一个是否公平分配。

2. 获取和释放许可

线程通过 acquire() 获取资源,如果没有可用资源,线程会被阻塞。资源释放后,线程能够继续执行。release() 用于归还资源。

3. 动态扩容

Semaphore 的动态扩容功能确保了资源的高效利用。例如,初始化时设置了4个资源,线程每次获取1个,当有线程释放时,系统会自动扩容以满足新的需求。这突破了传统的固定并发度限制,使得资源分配更加灵活。

4. 其他方法

  • acquire(int permits):动态获取指定数量的资源。
  • release(int permits):动态释放指定数量的资源。
  • availablePermits():获取当前可用的资源数量。
  • drainPermits():清空所有可用资源。
  • hasQueuedThreads():判断是否有线程在等待资源。
  • tryAcquire(int permits):尝试获取资源,返回布尔值。
  • tryAcquire(int permits, long timeout, TimeUnit unit):尝试获取资源,超时可自定义。

4. 应用场景

1. 并发控制

在多线程应用中,信号量用于控制线程的并发数量。例如,在 Web服务器环境下,信号量可以保障网路连接的处理单例性。

2. 资源分配

任何可以被多次占用的共享资源都可以用信号量来管理。例如,数据库连接池、文件资源等。

3. 优化性能

合理使用信号量可以避免死锁和资源泄漏,提升系统性能。例如,在资源收集和连接池管理中,信号量提供了响应式的资源调度机制。

5. 总结

信号量是 Java 多线程应用中的核心机制之一。它通过互斥锁和许可集的管理,为线程间的资源竞争提供了有序的解决方案。在实际应用中,信号量的灵活使用能够显著提升线程的执行效率和系统的整体性能。通过合理配置信号量,开发者能够更好地管理线程的并发执行,避免资源竞争和 deadlock 问题。同时,理解信号量的动态扩容机制,能够使系统在面对突发负载时具备更高的弹性和响应速度。

转载地址:http://guizk.baihongyu.com/

你可能感兴趣的文章
mysql 内连接、自然连接、外连接的区别
查看>>
mysql 写入慢优化
查看>>
mysql 分组统计SQL语句
查看>>
Mysql 分页
查看>>
Mysql 分页语句 Limit原理
查看>>
MySQL 创建新用户及授予权限的完整流程
查看>>
mysql 创建表,不能包含关键字values 以及 表id自增问题
查看>>
mysql 删除日志文件详解
查看>>
mysql 判断表字段是否存在,然后修改
查看>>
mysql 协议的退出命令包及解析
查看>>
mysql 取表中分组之后最新一条数据 分组最新数据 分组取最新数据 分组数据 获取每个分类的最新数据
查看>>
mysql 多个表关联查询查询时间长的问题
查看>>
mySQL 多个表求多个count
查看>>
mysql 多字段删除重复数据,保留最小id数据
查看>>
MySQL 多表联合查询:UNION 和 JOIN 分析
查看>>
MySQL 大数据量快速插入方法和语句优化
查看>>
mysql 如何给SQL添加索引
查看>>
mysql 字段区分大小写
查看>>
mysql 字段合并问题(group_concat)
查看>>
mysql 字段类型类型
查看>>