广告位联系
返回顶部
分享到

Java中Semaphore(信号量)的使用方法

java 来源:互联网搜集 作者:秩名 发布时间:2019-08-04 21:33:43 人浏览
摘要

本篇文章介绍Java中Semaphore(信号量)的使用方法 Semaphore的作用: 在java中,使用了synchronized关键字和Lock锁实现了资源的并发访问控制,在同一时间只允许唯一了线程进入临界区访问资源(读锁除外),这样子控制的主要目的是为了解决多个线程并发同一资源

本篇文章介绍Java中Semaphore(信号量)的使用方法

Semaphore的作用:

在java中,使用了synchronized关键字和Lock锁实现了资源的并发访问控制,在同一时间只允许唯一了线程进入临界区访问资源(读锁除外),这样子控制的主要目的是为了解决多个线程并发同一资源造成的数据不一致的问题。在另外一种场景下,一个资源有多个副本可供同时使用,比如打印机房有多个打印机、厕所有多个坑可供同时使用,这种情况下,Java提供了另外的并发访问控制--资源的多副本的并发访问控制,今天学习的信号量Semaphore即是其中的一种。

Semaphore实现原理初探:

Semaphore是用来保护一个或者多个共享资源的访问,Semaphore内部维护了一个计数器,其值为可以访问的共享资源的个数。一个线程要访问共享资源,先获得信号量,如果信号量的计数器值大于1,意味着有共享资源可以访问,则使其计数器值减去1,再访问共享资源。

如果计数器值为0,线程进入休眠。当某个线程使用完共享资源后,释放信号量,并将信号量内部的计数器加1,之前进入休眠的线程将被唤醒并再次试图获得信号量。

就好比一个厕所管理员,站在门口,只有厕所有空位,就开门允许与空侧数量等量的人进入厕所。多个人进入厕所后,相当于N个人来分配使用N个空位。为避免多个人来同时竞争同一个侧卫,在内部仍然使用锁来控制资源的同步访问。

Semaphore的使用:

Semaphore使用时需要先构建一个参数来指定共享资源的数量,Semaphore构造完成后即是获取Semaphore、共享资源使用完毕后释放Semaphore。

Semaphore semaphore = new Semaphore(10,true);
semaphore.acquire();
//do something here
semaphore.release();

下面的代码就是模拟控制商场厕所的并发使用:

public class ResourceManage { 
  private final Semaphore semaphore ; 
  private boolean resourceArray[]; 
  private final ReentrantLock lock; 
  public ResourceManage() { 
    this.resourceArray = new boolean[10];//存放厕所状态 
    this.semaphore = new Semaphore(10,true);//控制10个共享资源的使用,使用先进先出的公平模式进行共享;公平模式的信号量,先来的先获得信号量 
    this.lock = new ReentrantLock(true);//公平模式的锁,先来的先选 
    for(int i=0 ;i<10; i++){ 
      resourceArray[i] = true;//初始化为资源可用的情况 
    } 
  } 
  public void useResource(int userId){ 
 semaphore.acquire(); 
    try{ 
      //semaphore.acquire(); 
      int id = getResourceId();//占到一个坑 
      System.out.print("userId:"+userId+"正在使用资源,资源id:"+id+"\n"); 
      Thread.sleep(100);//do something,相当于于使用资源 
      resourceArray[id] = true;//退出这个坑 
    }catch (InterruptedException e){ 
      e.printStackTrace(); 
    }finally { 
      semaphore.release();//释放信号量,计数器加1 
    } 
  } 
  private int getResourceId(){ 
    int id = -1; 
 lock.lock();
    try { 
      //lock.lock();//虽然使用了锁控制同步,但由于只是简单的一个数组遍历,效率还是很高的,所以基本不影响性能。 
      for(int i=0; i<10; i++){ 
        if(resourceArray[i]){ 
          resourceArray[i] = false; 
          id = i; 
          break; 
        } 
      } 
    }catch (Exception e){ 
      e.printStackTrace(); 
    }finally { 
      lock.unlock(); 
    } 
    return id; 
  } 
} 
public class ResourceUser implements Runnable{ 
  private ResourceManage resourceManage; 
  private int userId; 
  public ResourceUser(ResourceManage resourceManage, int userId) { 
    this.resourceManage = resourceManage; 
    this.userId = userId; 
  } 
  public void run(){ 
    System.out.print("userId:"+userId+"准备使用资源...\n"); 
    resourceManage.useResource(userId); 
    System.out.print("userId:"+userId+"使用资源完毕...\n"); 
  } 
  
  public static void main(String[] args){ 
    ResourceManage resourceManage = new ResourceManage(); 
    Thread[] threads = new Thread[100]; 
    for (int i = 0; i < 100; i++) { 
      Thread thread = new Thread(new ResourceUser(resourceManage,i));//创建多个资源使用者 
      threads[i] = thread; 
    } 
    for(int i = 0; i < 100; i++){ 
      Thread thread = threads[i]; 
      try { 
        thread.start();//启动线程 
      }catch (Exception e){ 
        e.printStackTrace(); 
      } 
    } 
  } 
}

最后,Semaphore除了控制资源的多个副本的并发访问控制,也可以使用二进制信号量来实现类似synchronized关键字和Lock锁的并发访问控制功能。


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://blog.csdn.net/zbc1090549839/article/details/53389602
相关文章
  • SpringBoot自定义错误处理逻辑介绍

    SpringBoot自定义错误处理逻辑介绍
    1. 自定义错误页面 将自定义错误页面放在 templates 的 error 文件夹下,SpringBoot 精确匹配错误信息,使用 4xx.html 或者 5xx.html 页面可以打印错误
  • Java实现手写一个线程池的代码

    Java实现手写一个线程池的代码
    线程池技术想必大家都不陌生把,相信在平时的工作中没有少用,而且这也是面试频率非常高的一个知识点,那么大家知道它的实现原理和
  • Java实现断点续传功能的代码

    Java实现断点续传功能的代码
    题目实现:网络资源的断点续传功能。 二、解题思路 获取要下载的资源网址 显示网络资源的大小 上次读取到的字节位置以及未读取的字节
  • 你可知HashMap为什么是线程不安全的
    HashMap 的线程不安全 HashMap 的线程不安全主要体现在下面两个方面 在 jdk 1.7 中,当并发执行扩容操作时会造成环形链和数据丢失的情况 在
  • ArrayList的动态扩容机制的介绍

    ArrayList的动态扩容机制的介绍
    对于 ArrayList 的动态扩容机制想必大家都听说过,之前的文章中也谈到过,不过由于时间久远,早已忘却。 所以利用这篇文章做做笔记,加
  • JVM基础之字节码的增强技术介绍

    JVM基础之字节码的增强技术介绍
    字节码增强技术 在上文中,着重介绍了字节码的结构,这为我们了解字节码增强技术的实现打下了基础。字节码增强技术就是一类对现有字
  • Java中的字节码增强技术

    Java中的字节码增强技术
    1.字节码增强技术 字节码增强技术就是一类对现有字节码进行修改或者动态生成全新字节码文件的技术。 参考地址 2.常见技术 技术分类 类
  • Redis BloomFilter布隆过滤器原理与实现

    Redis BloomFilter布隆过滤器原理与实现
    Bloom Filter 概念 布隆过滤器(英语:Bloom Filter)是1970年由一个叫布隆的小伙子提出的。它实际上是一个很长的二进制向量和一系列随机映射
  • Java C++算法题解leetcode801使序列递增的最小交换次

    Java C++算法题解leetcode801使序列递增的最小交换次
    题目要求 思路:状态机DP 实现一:状态机 Java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution { public int minSwap(int[] nums1, int[] nums2) { int n
  • Mybatis结果集映射与生命周期介绍

    Mybatis结果集映射与生命周期介绍
    一、ResultMap结果集映射 1、设计思想 对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了 2、resultMap的应用场
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计