信号量使用例子

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

当处理访问公共资源的并发线程时,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

信号量使用例子

信号量使用例子_用信号量锁定:一个例子相关推荐

  1. 判断sem信号量为零_将信号量递减为零的进程崩溃时,如何恢复信号量?

    我有多个使用g ++编译的应用程序,它们在Ubuntu中运行.我正在使用命名信号量来协调不同进程之间的关系. 除非 出现以下情况, 否则 所有方法都可以正常工作:如果其中一个进程调用sem_wait( ...

  2. react做h5 例子_使用React写一个网站的心得体会

    网站是毕业设计的作品,开发这个网站的目的主要用于记录一些笔记,以及聚合一些资讯信息,也算自己在网络世界中的一块静地吧,可以在这里一些技术上想法的实践. 网站最初前端使用vue开发,在前段时间由于项目的 ...

  3. java protobuf 例子_用 Maven 实现一个 protobuf 的 Java语言例子

    1. 介绍Protocol Buffers 在我们学习Java语言的路上,我们知道Protocal Buffers(简称protobuf)是谷歌的一项技术,用于结构化的数据序列化.反序列化,常用于RP ...

  4. java protobuf 例子_用Maven实现一个protobuf的Java例子

    注:试验环境在Mac Idea环境下 1. 介绍Protocol Buffers Protocal Buffers(简称protobuf)是谷歌的一项技术,用于结构化的数据序列化.反序列化,常用于RP ...

  5. 质量属性效用树例子_数百个 HTML5 例子学习 HT 图形组件 – 拓扑图篇

    HT 是啥:Everything you need to create cutting-edge 2D and 3D visualization. 这口号是当年心目中的产品方向,接着就朝这个方向慢慢打 ...

  6. java抽象类例子_关于java抽象类的例子

    在网上找了很久,发现没有一个比较好的关于java抽象类的例子,刚好自己这些天在书上看到一个不错的猜数字游戏的例子,所以拿出来改进了下,希望能给你一些帮助,具体内容如下 建2个类依次为AbstractG ...

  7. python加法例子_第二讲 做加法的例子

    # Django Step by Step (二) ## 1 引言 随着学习,我们的例子也开始复杂了,下一步我想实现一个简单的 web 加法器.界面会是这样: ![](https://img.kanc ...

  8. java多态的简单例子_要JAVA的简单例子,继承\多态的,详细讲解运行的每一步

    java中的多态是动态绑定的,也就是说在编译期不能确定一个方法的执行体是哪个方法(在继承中重写的方法).执行果支委会根据在堆上分配的的引用去寻找方法体,所以产生你你所不想要的结果是正常的也是正确的.改 ...

  9. 咬文嚼字的有趣例子_咬文嚼字的古今中外的例子

    推敲的来历 唐朝的贾岛是著名的苦吟派诗人.什么叫苦吟派呢?就是为了一句诗或是诗中的一个词,不惜耗费心血,花费工夫.贾岛曾用几年时间做了一首诗.诗成之后,他热泪横流,不仅仅是高兴,也是心疼自己.当然他并 ...

最新文章

  1. 注册asp.net 4.0 到iis
  2. k8s中几种port介绍
  3. hibernate中报错could not initialize proxy - no Session的解决方法
  4. 马尔可夫Markov决策过程 MDP、马尔可夫奖励过程MRP
  5. python华容道最短路径_NOIp2013D2T3 华容道【搜索图论-最短路】
  6. 【Kafka】Kafka IllegalArgumentException: Could not find a ‘KafkaClient‘ entry in the JAAS configuratio
  7. 跟着开涛springmvc学习(转)
  8. 深度学习之RNN循环神经网络(理论+图解+Python代码部分)
  9. Ubuntu 64 测试ODB
  10. Overland Conveyor Belt Analyst 15.0.19.zip
  11. 国外的一个网站不能够访问
  12. 分布式项目Maven打包出现Could not resolve dependencies for project、Could not find artifact问题解决
  13. 利用个人PC建设小型服务器
  14. java target文件夹_Maven不会创建“/ target / m2e-wtp / web-resources”文件夹
  15. 华南师范大学计算机学院联系方式,华南师范大学计算机学院导师介绍:曾碧卿...
  16. 广东诚美计算机专修学院 概况,广州各大高校
  17. 珞石经销商—珞石协作机器人xMate3的标定方法
  18. 常规保养配件信息查询api接口
  19. HTML+CSS静态页面网页设计作业——2019凡客服装店铺商城(1页) HTML+CSS+JavaScript HTML+CSS大作业_ 服装店铺网页制作作业_购物网页设计...
  20. erdas裁剪影像_在arcgis、ERDAS下如何进行影像图裁剪

热门文章

  1. 读取/书写Java的XML格式properties文件
  2. 直面Java第45期
  3. 关于 NIO 你不得不知道的一些“地雷”
  4. String.format()方法的使用
  5. java导出javadoc文档
  6. 深入C#中的String类
  7. 巧妙使用信用卡N个小技巧
  8. 面向对象VS面向过程
  9. rabbitmq生产者基于事务实现发送确认
  10. 本地方法(JNI)——使用调用API