信号量使用例子_用信号量锁定:一个例子

信号量使用例子

并发是带来有趣挑战的一个方面。 如果处理不当,会带来种族问题,这会使人们感到困惑,因为这些问题有时会突然出现,并且有时会正常工作。

当处理访问公共资源的并发线程时,Java语言提供了许多处理竞争条件的方法。 一些包括;

  1. 使用volatile关键字
  2. 使用java.util.concurrent和 java.util.concurrent.atomic中可用的类
  3. 同步块
  4. 使用信号量

当然,可能还有更多我可能不知道的事情。 今天,我想向大家展示的例子是使用
信号量 。 它是从JDK 1.5引入的,使开发人员能够无缝获取和释放锁。 同样,我将展示的示例是一个假设的场景,该场景仅用于描述使用信号量可以实现的效果,因此请不要关注代码的固有细节:)。

因此,在这种情况下,存在一个内存缓存中保存了类型为
'人'。 用户可以使用缓存插入和检索记录。 这里的问题是我们将使用信号量来控制对内存缓存的并发访问。 现在,我不想给您带来更多文本,让我们开始业务并显示一些代码;

import java.util.concurrent.Semaphore;/*** This class will allow thread to acquire and release locks as required* * @author dinuka.arseculeratne* */
public class PersonLock {/*** We do not want multiple lock objects lying around so we make ths class* singleton*/private PersonLock() {}/*** Bill Pugh's way of lazy initializing the singleton instance* * @author dinuka.arseculeratne* */private static class SingletonHolder {public static final PersonLock INSTANCE = new PersonLock();}/*** Use this method to get a reference to the singleton instance of* {@link PersonLock}* * @return the singleton instance*/public static PersonLock getInstance() {return SingletonHolder.INSTANCE;}/*** In this sample, we allow only one thread at at time to update the cache* in order to maintain consistency*/private Semaphore writeLock = new Semaphore(1);/*** We allow 10 concurrent threads to access the cache at any given time*/private Semaphore readLock = new Semaphore(10);public void getWriteLock() throws InterruptedException {writeLock.acquire();}public void releaseWriteLock() {writeLock.release();}public void getReadLock() throws InterruptedException {readLock.acquire();}public void releaseReadLock() {readLock.release();}
}

此类将处理获取和释放使我们的缓存线程安全所需的锁的过程。 我在这里使用了两个单独的锁来进行读写。 其背后的原理是允许用户读取数据,尽管在读取时可能已过时。

请注意,我已经使用
这里的“十”表示十个线程可以同时获取锁并出于读取目的访问缓存。 接下来,您可以在写入锁定中看到,我已经使用了“
一个”表示一次只能有一个线程可以访问缓存以将项目放入缓存。 这对于维护缓存内的一致性很重要。 也就是说,我不希望有多个线程试图将项目插入到地图中,这将导致不可预测的行为(至少在某些情况下)。 使用信号量获取锁主要有两种方法。

1. Acquisition() :是一个阻塞调用,它等待直到释放锁或线程被中断为止

2. tryAcquire() :是一个非阻塞调用,它将立即返回并返回true或false,表示是否已获得锁定。

在这里,我使用了阻塞获取调用,因为我希望线程等待直到锁可用。 当然,这取决于您的用例。 您还可以在tryAcquire()方法中定义超时期限,以使线程不会无限期地等待锁定。

接下来,下面的存储类显示了我如何使用锁类在缓存中插入和读取数据。

import java.util.HashMap;
import java.util.Map;/*** A mock storage to hold the person objects in a map* * @author dinuka.arseculeratne* */
public class PersonStorage {private Map<Integer, Person> personCache = new HashMap<Integer, Person>();private int counter = 0;/*** This class is made singleton and hence the constructor is made private*/private PersonStorage() {}/*** Bill Pugh's way of lazy initializing the singleton instance* * @author dinuka.arseculeratne* */private static final class SingletonHolder {public static final PersonStorage INSTANCE = new PersonStorage();}/*** Use this method to get a reference to the singleton instance of* {@link PersonStorage}* * @return the singleton instance*/public static PersonStorage getInstance(){return SingletonHolder.INSTANCE;}/*** Inserts the person into the map. Note that we use defensive copying so* that even if the client changes the object later on, those changes will* not be reflected in the object within the map* * @param person*            the instance of {@link Person} to be inserted* @return the key which signifies the location of the person object* @throws InterruptedException*/public int putPerson(Person person) throws InterruptedException {Person copyPerson = person.copyPerson();personCache.put(++counter, copyPerson);return counter;}/*** Here as well we use defensive copying so that the value of the object* reference within the map is not passed in to the calling party.* * @param id*            the id representing the location of the object within the map* @return the instance of the {@link Person} represented by the key passed*         in* @throws InterruptedException*/public Person retrievePerson(int id) throws InterruptedException {PersonLock.getInstance().getReadLock();if (!personCache.containsKey(id)) {throw new RuntimeException('Key is not found');}PersonLock.getInstance().releaseReadLock();return personCache.get(id).copyPerson();}}

显然,代码也可以在没有锁的情况下工作,但是问题是应用程序将不一致,并且每次运行都会提供不同的结果。 这不是您希望应用程序执行的操作,因此使用锁可以确保应用程序始终运行。

最后是一个小型测试类,以展示其工作方式; 并不是在这里我们在调用putPerson()方法之前获得了锁,并在finally块中释放了该锁,以确保释放该锁。

/*** A test class to demonstrate the locking at work* * @author dinuka.arseculeratne* */
public class TestLock {public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {Person p1 = new Person(1L, 'Test1', 'XYZ');try {
PersonLock.getInstance().getWriteLock();
PersonStorage.getInstance().putPerson(p1);} catch (InterruptedException e) {// Exception handling need to be donee.printStackTrace();}finally{PersonLock.getInstance().releaseWriteLock();}}});Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {Person p2 = new Person(2L, 'Test123', 'ABC');try {
PersonLock.getInstance().getWriteLock();PersonStorage.getInstance().putPerson(p2);} catch (InterruptedException e) {// Exception handling need to be done}finally{PersonLock.getInstance().releaseWriteLock();}}});t1.start();t2.start();System.out.println(PersonStorage.getInstance().retrievePerson(2));}
}

以上是我对使用Sempahores来确保代码线程安全的简短介绍的总结,对于任何想使用该代码的人来说,都可以从
在这里 。 尝试删除Storage类中的锁,并查看其在每次运行中的行为。 您将看到可能发生的比赛情况。

参考: 使用信号灯锁定:我们的JCG合作伙伴 Dinuka Arseculeratne 的示例,来自“ IT之旅”博客。


翻译自: https://www.javacodegeeks.com/2012/10/locking-with-semaphore-example.html

信号量使用例子

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/352289.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.net Reactor之exe、dll文件混淆

.net Reactor之exe、dll文件混淆 .net Reactor的主要功能&#xff1a; 1.是对dll文件、exe文件进行反编译混淆 2.对dll进行内部加锁&#xff0c;限制其使用的固定机器、固定时间、部署次数 2.创建证书文件&#xff0c;用证书管理其限制的机器、时间、部署次数 页面&#xff1a;…

简述SAS逻辑库的概念及建立方法。什么是临时库和永久库?

libname student e:\mysas;SAS中利用libname命令建立逻辑库&#xff0c;虽然之后建立的与其关联的永久数据集还保存在该逻辑库所指的目录中&#xff0c;但重启SAS后该库却没有显示于库目录中。 例如e:\mysas目录已存在&#xff0c;程序data student.aaa;……重启SAS后虽然数据集…

35 岁 学python 必要_程序员:Python学不学?完全没必要纠结

随着云计算、大数据、人工智能的大量应用&#xff0c;Python这毛头小子&#xff0c;成了当红炸子鸡&#xff0c;香飘四溢&#xff0c;撒播到互联网的每个角落里。1几家欢喜几家愁&#xff0c;欢喜的人&#xff0c;早就用上了&#xff0c;国外的Twitter、Google、Yahoo&#xff…

了解连接池

1.简介 连接池是一种通过在池中打开和管理N个数据库连接来提高应用程序性能的技术。 该应用程序只是请求连接&#xff0c;使用它&#xff0c;然后将其放回池中。 当应用程序需要连接时&#xff0c;就绪连接将保持可用状态&#xff0c;以供池中使用。 池管理连接生命周期&#x…

linux上很方便的上传下载文件工具rz和sz

linux上很方便的上传下载文件工具rz和sz(本文适合linux入门的朋友) ######################################################### #《老男孩linux就业培训中心-初级班第七期第一节内容总结。 #linux上很方便的上传下载文件工具rz和sz #date:2011-06-15 #作者&#xff1a;老男孩…

SAS学习︱逻辑库、数据集创建与查看、数据库链接(SAS与R的code对照)

一、逻辑库、数据集、数据字典 数据字典>逻辑库>数据集 逻辑库工作空间&#xff0c;存储四类内容&#xff0c;test是数据集文件&#xff0c;views是视图&#xff08;相当于R里面的views点击查看&#xff09;&#xff0c;formats代表文件&#xff0c;sasmacr代表目录内容…

sqlserver 如何把一列分为一行显示_SqlServer数据库如何快速修改表的一列值

工作中我们会遇到一个表的一列值需要进行整体更换为另一个表的某个字段的值&#xff0c;那么我们该如何处理呢&#xff1f;数据源Room表新的Room表现将Room表的RoomTypeID列替换成Room_new表的RoomTypeID方法一&#xff1a;直接修改update Room set RoomTypeID (select RoomTy…

Linux 命令行通配符及转义符的实现

我们想对一类文件批量操作&#xff0c;例如批量查看硬盘文件属性&#xff0c;那么正常命令会是&#xff1a; [rootlinuxprobe ~]# ls /dev/sda [rootlinuxprobe ~]# ls /dev/sda1 [rootlinuxprobe ~]# ls /dev/sda2 [rootlinuxprobe ~]# ls /dev/sda3 但有些时候确实不知道分区…

windows python 访问mtp存储空间_用Windows电脑训练深度学习模型?超详细配置教程来了...

虽然大多数深度学习模型都是在 Linux 系统上训练的&#xff0c;但 Windows 也是一个非常重要的系统&#xff0c;也可能是很多机器学习初学者更为熟悉的系统。要在 Windows 上开发模型&#xff0c;首先当然是配置开发环境。Kaggle Master 及机器学习实践者 Abhinand 立足于自己的…

Matlab自带排序函数sort用法

Matlab自带排序函数sort用法 [Y,I] sort(X,DIM,MODE) sort函数默认Mode为ascend为升序&#xff0c;sort(X,descend)为降序排列。 sort(X)若X是矩阵&#xff0c;默认对X的各列进行升序排列 sort(X,dim) dim1时等效sort(X) dim2时表示对X中的各行元素升序排列 Matlab中给一维向量…

PostgreSQL学习手册(数据表)

一、表的定义&#xff1a; 对于任何一种关系型数据库而言&#xff0c;表都是数据存储的最核心、最基础的对象单元。现在就让我们从这里起步吧。 1. 创建表&#xff1a; CREATE TABLE products ( product_no integer, name text, price nu…

织梦联动类别-地区调用不显示第三级城市的解决方法

织梦联动类别-地区调用不显示第三级城市的原因 1、附加表dede_addoninfos 或者 你的其他表中的字段nativeplace数据类型为int型&#xff0c;无法保存第三级城市对应的的evalue值(比如&#xff1a;东山区 对应的 10001.001) 2、枚举表dede_sys_enum中的第三级城市对应evalue值…

js 随机1-10随机数_寻找随机的错误-一个真实的故事

js 随机1-10随机数几周前&#xff0c;我完成了RapidFTR开源项目的错误查找 &#xff0c;这花了我三个晚上。 我认为可能值得分享狩猎的故事。 本文将介绍我的工作。 我将概述我的旅程&#xff0c;以便真正找到正在发生的事情的根本原因。 我在本文中的目标是突出显示可以使用的…

用python写九九乘法口诀表左上角_python打出九九乘法口诀表

用IDLE打出乘法口诀表&#xff0c;想要就是如下图的结果&#xff1a;实现算法很简单&#xff0c;但是IDLE(python3.7)默认的换行输出方式不太容易实现&#xff0c;得需费一番脑筋。代码如下&#xff1a;*row0 #设置行数&#xff0c;值为1时候…

设计模式(一)Chain Of Responsibility责任链模式

设计模式篇章&#xff0c;源于网课的学习&#xff0c;以及个人的整理 在我们接收用户提交的字符时&#xff0c;常常会使用到过滤&#xff0c;在学习责任链模式前&#xff0c;我们是这样做的 1.定义一个类 public class MsgProcesser {String msg;public MsgProcesser(String ms…

如果你是IT技术人员,请思考这15个问题

行内的人自嘲是程序猿、屌丝和码农&#xff0c;行外的人也经常拿IT人调侃&#xff0c;那么究竟是IT人没有价值&#xff0c;还是没有仔细思考过自身的价值&#xff1f; 1.搞IT的是屌丝、码农、程序猿&#xff1f; 人们提到IT人的时候&#xff0c;总会想到他们呆板、不解风情&…

在Windows上运行-XX:CompileCommand

HotSpot JVM提供了几个与即时 &#xff08; JIT &#xff09;编译有关的命令行参数。 在本文中&#xff0c;我介绍了开始应用命令行标志-XX&#xff1a;CompileCommand所需的步骤&#xff0c;以查看对单个方法执行的即时编译。 JIT概述 Nikita Salnikov-Tarnovski的博客文章您…

匹配中文字符的正则表达式: [u4e00-u9fa5](

匹配双字节字符(包括汉字在内)&#xff1a;[^x00-xff]评注&#xff1a;可以用来计算字符串的长度&#xff08;一个双字节字符长度计2&#xff0c;ASCII字符计1&#xff09;匹配空白行的正则表达式&#xff1a;ns*r评注&#xff1a;可以用来删除空白行匹配HTML标记的正则表达式&…

python define function的顺序_Python怎么根据一个函数来决定列表顺序

def__init__(self,function):self._queue[]self.functionfunction然后要写一往列表里增加元素的方法&#xff0c;按照function排序&#xff0c;function类型为函数defadd(self,item):"""AddtothisP...def __init__(self,function):self._queue []self.function…

excel单元格内容合并

这几天在整理数据&#xff0c;有时候数据都在表格的不同单元格中&#xff0c;想把两格内容合并为一格&#xff0c;于是验证了两种方法方法一:(1)在B1输入公式A1&B1(2)做完第一步后,选中B1后,鼠标移到单元格右下出现“”符号是下拉,就能得到结果,如图:方法二(1)在B1输入公式…