JUC学习系列八(信号量 Semaphore)

2023-10-28

一个计数信号量。从概念上讲,信号量维护了一个许可集。Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。通常,应该将用于控制资源访问的信号量初始化为公平的,以确保所有线程都可访问资源。为其他的种类的同步控制使用信号量时,非公平排序的吞吐量优势通常要比公平考虑更为重要。此类还提供便捷的方法来同时 acquire释放多个许可。小心,在未将公平设置为 true 时使用这些方法会增加不确定延期的风险。

实例:个人感觉信号量类似限流的阀门,控制流量。下面的实例就是控制线程进入的数目

public class SemaphoreTest {

    public void printName(Semaphore sh){
        try {
            sh.acquire();
            System.out.println("当前运行的线程为:"+Thread.currentThread().getName());
            TimeUnit.SECONDS.sleep(1);
            sh.release();
        } catch ( Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        final Semaphore semaphore=new Semaphore(5,true);
//        final Semaphore semaphore=new Semaphore(5);  //非公平的
        final SemaphoreTest sht=new SemaphoreTest();
        //每次只能进入5个线程,每次等一秒,这里有100个线程,大致是20S的时间
        Long startTime=System.currentTimeMillis();
        for (int i=0;i<100;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    sht.printName(semaphore);
                }
            }).start();
        }
        //自旋等待所有线程执行完毕
        // 当前线程组中,主线程存活,另外一个我猜测应该是维护semaphore的线程。
        while (Thread.activeCount()>2){
        }
        Long endTime=System.currentTimeMillis();
        System.out.println("总计:"+(endTime - startTime));
    }


}

 

上面就是信号量的简单使用方法,下面是API里常用方法,原理和源码后面有时间会补上。

 

源码剖析

结构:

构造方法:

释放方法流程剖析:

当操作成功时,信号量会放任此线程通过;当修改操作失败,应该是根据信号量允许进入的值有关,跟State有联系。compareAndSetState()操作涉及到了Unsafe类,这个类的方法全是调用C库的东西。除非有openJDK,不然看不到具体实现。我看不到源码,也不知道这个CAS操作是怎么处理的,走了几次断点,如下:

这个是current=3,next=4,CAS操作失败,没有返回true。

这个是current=4,next=5,可以看到CAS操作成功了,断点已经走到return那里。

CAS操作是调用AQS里的方法:

 这个是Unsafe类里面的方法:

  

 网上给出的CAS的一些解释:

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JUC学习系列八(信号量 Semaphore) 的相关文章

  • 并发编程系列之Fork/Join

    前言 上节我们讲了阻塞队列 Java中的并发容器就算有了个基本的认识 今天我们来介绍一种线程工作模式 叫Fork Join 他是JDK7之后提供的一个并行执行框架 主要的思想我觉得是分而治之 将一个大的任务分成多个小的任务并行执行 然后等所
  • 【Java并发编程的艺术】Java并发容器和框架:Java中的阻塞队列

    1 什么是阻塞队列 阻塞队列常用于生产者和消费者的场景 生产者是向队列里添加元素的线程 消费者是 从队列里取元素的线程 阻塞队列就是生产者用来存放元素 消费者用来获取元素的容器 阻塞队列 BlockingQueue 是一个支持两个附加操作的
  • java.util.concurrent.locks.ReentrantReadWriteLock 读写锁

    读写锁简介 对共享资源有读和写的操作 且写操作没有读操作那么频繁 在没有写操作的时候 多个线程同时读一个资源没有任何问题 所以应该允许多个线程同时读取共享资源 但是如果一个线程想去写这些共享资源 就不应该允许其他线程对该资源进行读和写的操作
  • 悲观锁(Synchronized)和乐观锁(CAS)

    文章目录 悲观锁和乐观锁 Synchronized Synchronized使用 Synchronized底层原理 Java1 6对Synchronized的优化 synchronized的等待唤醒机制 CAS CAS使用 CAS底层原理
  • JUC三连问

    1 进程和线程的区别 1 进程是资源分配的基本单位 线程是程序执行的最小单位 2 一个进程包括多个线程 3 每个进程都有自己的内存和资源 一个进程中的线程会共享这些内存和资源 每个线程都有单独的栈内存 和寄存器 2 并行和并发的区别 并行指
  • JUC常用到的类

    JUC java util concurrent 并发包中包含了许多并发编程中需要用到的类 锁 如ReentratLock ReadWriteLock ReentrantLock重入锁 可以替代synchronized使用 并且有更多强大的
  • 159.并发编程(三):线程池,JUC

    目录 一 线程池 1 线程池的作用 2 手写线程池 3 ThreadPoolExecutor 1 线程池状态
  • java中的异步处理和Feature接口(一)

    文章目录 背景介绍 Feature接口 Feature接口和Tread的区别 Feature接口示例 Feature接口的局限性 背景介绍 想象这样一个场景 你可能希望为你的法国客户提供指定主题的热点报道 为实现这一功能 你需要向 谷歌或者
  • Java并发编程-第二章

    以下内容来自 Java并发编程 书籍第二章 补充 1 volatile的有序性 volatile通过内存屏障实现禁止指令重排序保证有序性 硬件层面的内存屏障分为Load Barrier 和 Store Barrier即读屏障和写屏障 2 同
  • AQS原理解析及源码分析

    目录 1 介绍下AQS几个重要的组件 2 内部成员变量state 3 同步队列NODE 4 等待队列 condition AbstractQueuedSynchronizer又称为队列同步器 后面简称AQS AQS的核心思想是 如果被请求的
  • 高并发,你真的理解透彻了吗?

    高并发 几乎是每个程序员都想拥有的经验 原因很简单 随着流量变大 会遇到各种各样的技术问题 比如接口响应超时 CPU load升高 GC频繁 死锁 大数据量存储等等 这些问题能推动我们在技术深度上不断精进 在过往的面试中 如果候选人做过高并
  • Java 线程池的submit的使用与分析.md

    在Java5以后 通过Executor来启动线程比用Thread的start 更好 在新特征中 可以很容易控制线程的启动 执行和关闭过程 还能使用线程池的特性 上一篇我们介绍了线程池的基本用法和特性 我们用的最多的是ExecutorServ
  • 并发编程系列之原子操作实现原理

    前言 上节我们讲了并发编程中最基本的两个元素的底层实现 同样并发编程中还有一个很重要的元素 就是原子操作 原子本意是不可以再被分割的最小粒子 原子操作就是指不可中断的一个或者一系列操作 那么今天我们就来看看在多处理器环境下Java是如何保证
  • 从0实现基于Linux socket聊天室-实现聊天室的公聊、私聊功能-4

    前面文章链接如下 从0实现基于Linux socket聊天室 多线程服务器模型 1 从0实现基于Linux socket聊天室 多线程服务器一个很隐晦的错误 2 从0实现基于Linux socket聊天室 实现聊天室的登录 注册功能 3 上
  • synchronized的作用和用法

    郁闷 参考 synchronized的作用和用法 Java中Synchronized的使用 文章目录 简单介绍 用法 实战实例 修饰代码块 修饰普通方法 修饰静态方法 简单介绍 synchronized关键字是用来控制线程同步的 就是在多线
  • ThreadPoolExecutor源码解析

    ThreadPoolExecutor源码解析 一 新建线程池的是构造方法 public ThreadPoolExecutor int corePoolSize int maximumPoolSize long keepAliveTime T
  • 深入理解synchronized底层原理,一篇文章就够了!

    文章目录 前言 一 synchronized的特性 1 1 原子性 1 2 可见性 1 3 有序性 1 4 可重入性 二 synchronized的用法 三 synchronized锁的实现 3 1 同步方法 3 2 同步代码块 四 syn
  • 进程、线程、管程、纤程、协程概念以及区别

    进程 进程是指在操作系统中能独立运行并作为资源分配的基本单位 由一组机器指令 数据和堆栈等组成的能独立运行的活动实体 进程在运行是需要一定的资源 如CPU 存储空间和I O设备等 进程是资源分配的基本单位 进程的调度涉及到的内容比较多 存储
  • 多线程实现事务回滚

    多线程实现事务回滚 特别说明CountDownLatch CountDownLatch的用法 CountDownLatch num 简单说明 主线程 mainThreadLatch await 和mainThreadLatch countD
  • Java 多线程模式 —— Guarded Suspension 模式

    Part1Guarded Suspension 模式的介绍 我们只从字面上看 Guarded Suspension 是受保护暂停的意思 1Guarded Suspension 模式 在实际的并发编程中 Guarded Suspension

随机推荐

  • 推挽电路和开集

    整理下之前的笔记 简谈推挽电路 要理解推挽输出 首先要理解好三极管 晶体管 的原理 下面这种三极管有三个端口 分别是基极 Base 集电极 Collector 和发射极 Emitter 下图是NPN型晶体管 这种三极管是电流控制型元器件 注
  • activiti报错:org.activiti.engine.ActivitiTaskAlreadyClaimedException: Task ‘12502‘ is already claimed

    在运行activiti时 报错信息如下 Exception in thread main org activiti engine ActivitiTaskAlreadyClaimedException Task 12502 is alrea
  • 中介者模式学习和思考

    一 概念 中介者模式 Mediator Mode 就是用一个中介对象来封装一系列的对象交互 中介者使各对象不需要显式地相互引用 从而使其耦合松散 而且可以独立地改变它们之间的交互 可以看出 中介者主要是通过中介对象来封装对象之间的关系 使之
  • 11.微信蓝牙操作

    一 操作蓝牙适配器的共有 4 个 分别是 wx openBluetoothAdapter 初始化蓝牙适配器 wx closeBluetoothAdapter 关闭蓝牙模块 wx getBluetoothAdapterState 获取本机蓝牙
  • 数据结构顺序栈的C语言实现(入栈,初始化栈,出栈,取栈顶操作)【C语言环境下可以直接运行】

    C语言实现顺序栈的 入栈 初始化栈 出栈 取栈顶操作 C语言数据结构 C语言环境下可以直接运行 这个程序可以运行的 虽然比较简单 但是是可以直接运行的 include
  • error connecting to master ‘repl@192.168.4.114:3306‘ - retry-time: 60  retries: 3

    mysql gt show slave status G 1 row Slave IO State Connecting to master Master Host 192 168 4 114 Master User repl Master
  • shell中的getopt

    Linux中的位置变量和预定义变量 shell中的getopts getopt是一个外部命令 不是bash内置命令 Linux发行版通常会自带 getopt支持短选项和长选项 老版本的getopt问题较多 增强版getopt比较好用 执行命
  • 6月之随便写点什么

    马上可能很长一段时间不会更新博客了 加油吧 后期再会 我的博客
  • Unity摄像机屏幕上画线(逐步完善)

    1 类似于星际公民用于飞船控制的线 从屏幕中心开始 鼠标位置结束 将下面脚本挂载至摄像机 using System Collections using System Collections Generic using System Thre
  • 在ESXi界面给虚拟机配的内核数与虚机内任务管理器显示数不一致

    source esxi6 7设备管理器中的cpu核数和任务管理器中的不一致 esxi吧 百度贴吧 ESXi里给某台win10虚机配置了16核cpu 但在此虚机里面的任务管理器里却只看到2个核心 原因在下图 把CPU和和每个插槽内核数改成一样
  • JavaSE学习 day01

    今天是学习JavaSE的第一天 首先 我先初识了Java 了解了学习目标 知道了什么是程序 什么是Java 为什么学习Java 然后 学习了搭建Java开发环境 1 安装JDK 2 配置环境变量 这里要注意 JDK java开发工具包 JR
  • JS中的函数-内部函数,子调用函数和返回值为函数的函数

    自调用函数 Self invoking Functions 自调用函数也是匿名函数的一种表现形式 这个函数在定义之后 直接调用 如下 function alert haha 看起来还挺怪异 不过确实很简单 自调用函数很方便使用 可以不用定义
  • 多个Node.js版本之间切换

    本篇文章会讲windows和Mac系统下实现多个node js版本之间的切换 1 windows下采用nvm nvm window 2 Mac下采用nvm和n 注 window和mac下的nvm地址是不一样的 一 windows系统 什么是
  • JDK 8 / JDK 1.8 压缩包

    文章大概 因为JDK8在官网是直接的一个exe可运行程序 并没有压缩包 而网络上有别人准备的压缩包 看到是某度盘直接放弃 所以这篇文章教大家自己来搞一个JDK8的压缩包文件 开始操作 在操作之前 你需要去Java Downloads Ora
  • 对象转JSONObject——字段空值处理方法

  • uniapp 发布微信小程序分包

    1 进入下列文件 进入 unpackage dist build mp weixin app json pages pages index index pages login login pages views WearCutData We
  • 十个漂亮的数学定理赏析

    原地址 十个漂亮的数学定理赏析 Beauty is the first test there is no permanent place in the world for ugly mathematics G H Hardy 科学家研究自然
  • MYSQL--基础--11--join理解

    MYSQL 基础 11 join理解 1 数据初始化 SET FOREIGN KEY CHECKS 0 Table structure for course DROP TABLE IF EXISTS course CREATE TABLE
  • GPT,GPT-2,GPT-3

    视频讲解 GPT GPT 2 GPT 3 论文精读 论文精读 哔哩哔哩 bilibili 论文链接 GPT https www cs ubc ca amuham01 LING530 papers radford2018improving p
  • JUC学习系列八(信号量 Semaphore)

    一个计数信号量 从概念上讲 信号量维护了一个许可集 Semaphore 通常用于限制可以访问某些资源 物理或逻辑的 的线程数目 通常 应该将用于控制资源访问的信号量初始化为公平的 以确保所有线程都可访问资源 为其他的种类的同步控制使用信号量