博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java并发——信号量Semaphore
阅读量:5778 次
发布时间:2019-06-18

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

简述

Semaphore(信号量)用来控制同时访问特定资源的线程数,它通过协调各个线程,以保证合理地使用公共资源

实现原理

Semaphore中管理着一组虚拟的许可(permit),许可的初始数量可通过构造函数来指定。在执行操作时需要首先获得许可(只要还有剩余的许可),并在使用以后释放许可。如果没有许可,那么acquire方法将阻塞直到有许可(或者直到被中断或者操作超时),当执行完业务通过release方法将许可归还,以便其他线程能够获得许可继续执行

构造方法

public Semaphore(int permits) {        sync = new NonfairSync(permits);    }         public Semaphore(int permits, boolean fair) {        sync = fair ? new FairSync(permits) : new NonfairSync(permits);    }复制代码

Semaphore内部基于sync实现,参数permits表示许可证数量,参数fair表示是否采取公平策略

公平策略

sync继承AQS,只需要重写其模板中的方法即可,acquire方法如下:

public void acquire() throws InterruptedException {        sync.acquireSharedInterruptibly(1);    }        /**     * AQS共享式获取同步状态模板方法(能响应中断)     */    public final void acquireSharedInterruptibly(int arg)            throws InterruptedException {        if (Thread.interrupted())            throw new InterruptedException();        if (tryAcquireShared(arg) < 0)            doAcquireSharedInterruptibly(arg);    }        protected int tryAcquireShared(int acquires) {        for (;;) {            // //判断该线程是否在队列的头部            if (hasQueuedPredecessors())                return -1;            // 获取当前剩余信号量许可                int available = getState();            // 计算acquire()之后,剩余的信号量许可数            int remaining = available - acquires;            // CAS设置信号量许可            if (remaining < 0 ||                compareAndSetState(available, remaining))                return remaining;        }    }复制代码

非公平策略

protected int tryAcquireShared(int acquires) {        return nonfairTryAcquireShared(acquires);    }        final int nonfairTryAcquireShared(int acquires) {        for (;;) {            int available = getState();            int remaining = available - acquires;            if (remaining < 0 ||                compareAndSetState(available, remaining))                return remaining;        }    }复制代码

公平与非公平区别在于公平策略会调用hasQueuedPredecessors()方法判断线程所关联的节点是否在队列头位置

释放

public void release() {        sync.releaseShared(1);    }        /**     * AQS共享式释放同步状态模板方法     */    public final boolean releaseShared(int arg) {        if (tryReleaseShared(arg)) {            doReleaseShared();            return true;        }        return false;    }        protected final boolean tryReleaseShared(int releases) {        for (;;) {            // 获取当前剩余许可数            int current = getState();            // 加上待释放许可数            int next = current + releases;            if (next < current) // overflow                throw new Error("Maximum permit count exceeded");            // CAS设置新许可数                if (compareAndSetState(current, next))                return true;        }    }复制代码

示例

public class SemaphoreTest {           public static void main(String[] args) {        final Semaphore semaphore = new Semaphore(3);        for (int i = 0; i < 10; i++) {            new Thread(new Runnable() {                @Override                public void run() {                    try {                        semaphore.acquire();                     System.out.println(Thread.currentThread().getName() + "进入车库");                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        e.printStackTrace();                    } finally {                        semaphore.release();                        System.out.println(Thread.currentThread().getName() + "出车库");                    }                }            }).start();        }    }      }复制代码

感谢

《java并发编程的艺术》

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

你可能感兴趣的文章
Java虚拟机管理的内存运行时数据区域解释
查看>>
人人都会深度学习之Tensorflow基础快速入门
查看>>
ChPlayer播放器的使用
查看>>
js 经过修改改良的全浏览器支持的软键盘,随机排列
查看>>
Mysql读写分离
查看>>
Oracle 备份与恢复学习笔记(5_1)
查看>>
Oracle 备份与恢复学习笔记(14)
查看>>
分布式配置中心disconf第一部(基本介绍)
查看>>
Scenario 9-Shared Uplink Set with Active/Active uplink,802.3ad(LACP)-Flex-10
查看>>
UML类图中的六种关系
查看>>
探寻Interpolator源码,自定义插值器
查看>>
一致性哈希
查看>>
mysql(待整理)
查看>>
使用PullToRefresh实现下拉刷新和上拉加载
查看>>
2012年电信业八大发展趋势
查看>>
Web日志安全分析工具 v2.0发布
查看>>
JS重载
查看>>
python2和python3同安装在Windows上,切换问题
查看>>
php加速工具xcache的安装与使用(基于LNMP环境)
查看>>
android超链接
查看>>