java面包屑实现_在Java中实现过滤器和面包店锁

java面包屑实现

为了了解锁的工作原理,实现自定义锁是一种好方法。 这篇文章将展示如何在Java上实现Filter和Bakery锁(自旋锁),并将它们的性能与Java的ReentrantLock进行比较。 过滤器锁和面包房锁满足互斥并且也是无饥饿算法,面包房锁是先到先服务的锁[1]。

为了进行性能测试,使用不同的锁类型,不同的线程数和不同的次数将计数器值递增到10000000。 测试系统配置为:Intel Core I7(具有8个内核,其中4个是真实的),Ubuntu 14.04 LTS和Java 1.7.0_60。

过滤器锁具有n-1个级别,可以视为“候诊室”。 获取锁之前,必须有一个线程穿过此等候室。 级别[2]有两个重要属性:

  1. 至少一个尝试进入级别l的线程成功。
  2. 如果有多个线程试图进入级别l ,则至少一个线程被阻止(即继续在该级别上等待)。

过滤器锁定的实现如下:

/**
* @author Furkan KAMACI
*/
public class Filter extends AbstractDummyLock implements Lock {
/* Due to Java Memory Model, int[] not used for level and victim variables.
Java programming language does not guarantee linearizability, or even sequential consistency,
when reading or writing fields of shared objects
[The Art of Multiprocessor Programming. Maurice Herlihy, Nir Shavit, 2008, pp.61.]
*/
private AtomicInteger[] level;
private AtomicInteger[] victim;
private int n;
/**
* Constructor for Filter lock
*
* @param n thread count
*/
public Filter(int n) {
this.n = n;
level = new AtomicInteger[n];
victim = new AtomicInteger[n];
for (int i = 0; i < n; i++) {
level[i] = new AtomicInteger();
victim[i] = new AtomicInteger();
}
}
/**
* Acquires the lock.
*/
@Override
public void lock() {
int me = ConcurrencyUtils.getCurrentThreadId();
for (int i = 1; i < n; i++) {
level[me].set(i);
victim[i].set(me);
for (int k = 0; k < n; k++) {
while ((k != me) && (level[k].get() >= i && victim[i].get() == me)) {
//spin wait
}
}
}
}
/**
* Releases the lock.
*/
@Override
public void unlock() {
int me = ConcurrencyUtils.getCurrentThreadId();
level[me].set(0);
}
}

面包店锁定算法通过使用面包店中经常使用的分布式版本的数字分配机来维护先到先得的属性:每个线程在门口取一个数字,然后等待,直到没有尝试使用更早编号的线程为止输入[3]。

面包店锁的实现如下:

/**
* @author Furkan KAMACI
*/
public class Bakery extends AbstractDummyLock implements Lock {
/* Due to Java Memory Model, int[] not used for level and victim variables.
Java programming language does not guarantee linearizability, or even sequential consistency,
when reading or writing fields of shared objects
[The Art of Multiprocessor Programming. Maurice Herlihy, Nir Shavit, 2008, pp.61.]
*/
private AtomicBoolean[] flag;
private AtomicInteger[] label;
private int n;
/**
* Constructor for Bakery lock
*
* @param n thread count
*/
public Bakery(int n) {
this.n = n;
flag = new AtomicBoolean[n];
label = new AtomicInteger[n];
for (int i = 0; i < n; i++) {
flag[i] = new AtomicBoolean();
label[i] = new AtomicInteger();
}
}
/**
* Acquires the lock.
*/
@Override
public void lock() {
int i = ConcurrencyUtils.getCurrentThreadId();
flag[i].set(true);
label[i].set(findMaximumElement(label) + 1);
for (int k = 0; k < n; k++) {
while ((k != i) && flag[k].get() && ((label[k].get() < label[i].get()) || ((label[k].get() == label[i].get()) && k < i))) {
//spin wait
}
}
}
/**
* Releases the lock.
*/
@Override
public void unlock() {
flag[ConcurrencyUtils.getCurrentThreadId()].set(false);
}
/**
* Finds maximum element within and {@link java.util.concurrent.atomic.AtomicInteger} array
*
* @param elementArray element array
* @return maximum element
*/
private int findMaximumElement(AtomicInteger[] elementArray) {
int maxValue = Integer.MIN_VALUE;
for (AtomicInteger element : elementArray) {
if (element.get() > maxValue) {
maxValue = element.get();
}
}
return maxValue;
}
}

对于此类算法,应提供或使用从0或1开始并以一个增量递增的线程id系统。 线程的名称为此目的进行了适当设置。 还应该考虑:Java编程语言在读取或写入共享对象的字段时不能保证线性化,甚至不能保证顺序一致性[4]。 因此,过滤器锁的级别和受害变量,面包店锁的标志和标签变量定义为原子变量。 一方面,想要测试Java内存模型效果的人可以将该变量更改为int []和boolean []并使用两个以上的线程运行算法。 然后,即使线程仍然存在,也可以看到该算法将针对Filter或Bakery挂起。

为了测试算法性能,实现了一个自定义计数器类,该类具有getAndIncrement方法,如下所示:

/**
* gets and increments value up to a maximum number
*
* @return value before increment if it didn't exceed a defined maximum number. Otherwise returns maximum number.
*/
public long getAndIncrement() {
long temp;
lock.lock();
try {
if (value >= maxNumber) {
return value;
}
temp = value;
value = temp + 1;
} finally {
lock.unlock();
}
return temp;
}

公平测试多个应用程序配置存在最大的障碍。 考虑的是:有很多工作(将变量递增到所需数量),并且在线程数量不同的情况下,完成它的速度有多快。 因此,为了进行比较,应该有一个“工作”平等。 此方法还使用该代码段测试不必要的工作负载:

if (value >= maxNumber) {
return value;
}

比较多个线程时,一种计算线程的单位工作性能的方法(即,不设置最大障碍,在循环中迭代到最大数量,然后将最后一个值除以线程数量)。

此配置用于性能比较:

线程数 1,2,3,4,5,6,7,8
重试计数 20
最大人数 10000000


这是包含标准误差的结果图表:

比较

首先,当您在Java中多次运行代码块时,会对代码进行内部优化。 当算法多次运行并且将第一输出与第二输出进行比较时,可以看到此优化的效果。 因此,第一经过时间通常应大于第二行。 例如:

currentTry = 0, threadCount = 1, maxNumber = 10000000, lockType = FILTER, elapsedTime = 500 (ms)
currentTry = 1, threadCount = 1, maxNumber = 10000000, lockType = FILTER, elapsedTime = 433 (ms)

结论

从图表中可以看出,“面包房锁”比“过滤器锁”要快,标准误差也很小。 原因是筛选器锁定的锁定方法。 在Bakery Lock中,作为一种公平的方法,线程是一个一个地运行的,但在Filter Lock中,它们是相互计算的。 与其他Java相比,Java的ReentrantLock具有最佳的性能。

另一方面,Filter Lock线性恶化,但Bakery和ReentrantLock却没有(当Lock Lock运行更多线程时,它可能具有线性图形)。 更多的线程数并不意味着更少的经过时间。 由于创建和锁定/解锁线程,所以2个线程可能比1个线程差。 当线程数开始增加时,Bakery和ReentrantLock的经过时间会变得更好。 但是,当线程数持续增加时,它就会变得更糟。 原因是运行算法的测试计算机的真实核心编号。

  • 可以从此处下载用于在Java中实现过滤器和面包店锁的源代码: https : //github.com/kamaci/filbak
  1. 多处理器编程的艺术。 莫里斯·赫里希(Maurice Herlihy),《尼尔·沙维特》,2008年,第31.-33页。
  2. 多处理器编程的艺术。 莫里斯·赫里希(Maurice Herlihy),尼尔·沙维特(Nir Shavit),2008年,第28页。
  3. 多处理器编程的艺术。 莫里斯·赫利希(Maurice Herlihy),《尼尔·沙维特》(Nir Shavit),2008年,第31页。
  4. 多处理器编程的艺术。 莫里斯·赫里希(Maurice Herlihy),尼尔·沙维特(Nir Shavit),2008年,第61页。

翻译自: https://www.javacodegeeks.com/2015/05/implementing-filter-and-bakery-locks-in-java.html

java面包屑实现

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

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

相关文章

postman 怎么调试pos_SpringBoot|第十五章:基于Postman的RESTful接口测试

前言从上一章节开始&#xff0c;接下来的几个章节会讲解一些开发过程中配套工具的使用。俗话说的好&#xff0c;工欲善其事&#xff0c;必先利其器。对于开发人员而言&#xff0c;有个好用的工具&#xff0c;也是一件事半功倍的事&#xff0c;而且开发起来也很爽&#xff0c;效…

spring配置jndi_在Spring Framework中通过JNDI进行配置

spring配置jndi从某个时候开始&#xff0c;应用程序必须是可配置的。 从第一个版本0.9开始&#xff0c;Spring Framework就为该问题提供了一个很好的辅助工具&#xff0c;该类为PropertyPlaceholderConfigurer类&#xff0c;而从Spring Framework 3.1开始&#xff0c;为Propert…

这几个C语言关键字你真的得懂(深度解剖)

点击蓝字关注我们1、什么是语句&#xff0c;表达式&#xff1f; 在C语言中 &#xff0c;凡是以分号隔开的就是一条语句&#xff1a;printf("hello world\n");a 1 2; ; (空语句)什么是表达式呢&#xff1f;C语言中&#xff0c;用各种操作符把变量连起来&#xff0c;…

aws sqs_JMS和AWS SQS的更多高级内容

aws sqs如您所知&#xff0c; AWS中的SQS SQS代表“简单队列服务”。 最近&#xff0c;在使用它的同时&#xff0c;我发现了将其称为“简单”的原因之一。 在之前的两篇文章&#xff08; 此处和此处 &#xff09;中&#xff0c;我展示了结合Spring Framework将SQS用作JMS队列提…

python 直方图每个bin中的值_【Python数据分析】四级成绩分布 -matplotlib,xlrd 应用...

标签&#xff1a; 最近获得了一些四级成绩数据&#xff0c;大概500多个&#xff0c;于是突发奇想是否能够看看这些成绩数据是否满足所谓的正态分布呢&#xff1f;说干就干&#xff0c;于是有了这篇文章。 文章顺带介绍了xlrd模块的一些用法和matplotlib画自定义数据的条形图和随…

adf开发_了解ADF生命周期中的ADF绑定

adf开发在这篇文章中&#xff0c;我将重点介绍ADF绑定层&#xff0c;并探讨当最初从浏览器请求带有一些数据的ADF页面时它如何工作。 Oracle ADF提供了自己的JSF生命周期扩展版。 实际上&#xff0c;ADF扩展了标准的JSF生命周期实现类&#xff0c;并提供了ADF阶段侦听器&#…

C语言实现计算器

点击蓝字关注我们1、实现逻辑首先创建菜单(menu)&#xff0c;把我们需要实现的功能打印到运行栏屏幕上。实现加法计算实现减法计算实现除法计算实现乘法计算退出计算器当然以上都是属于最基本的计算&#xff0c;你当然还可以实现一些其它计算。例如&#xff1a;位运算(按位与、…

python怎么创建txt文件啊_python根据txt文本批量创建文件夹

前言 前言&#xff1a;想写这个代码的原因是因为实习的时候需要根据表格名创建对应的文件夹&#xff0c;如果只是很少个数文件夹的话&#xff0c;ctrlshiftn还可以接受吧&#xff0c;可是一次就要创建几百个文件夹&#xff0c;这就有点方方了。所以我写了一些代码解决实际的问题…

jpa的查询api_为JPA的本机查询API键入安全查询

jpa的查询api当您使用JPA时-有时-JPQL不能解决问题&#xff0c;您将不得不使用本机SQL。 从一开始&#xff0c;像Hibernate这样的ORM就为这些情况保留了开放的“后门”&#xff0c;并为Spring的JdbcTemplate &#xff0c; Apache DbUtils或jOOQ提供了类似的API&#xff0c;用于…

十道题带你手撕二叉树

点击蓝字关注我们1、单值二叉树题目&#xff1a;思路一&#xff1a;&#xff08;遍历的方法&#xff09;将根节点的值与二叉树中的每一个节点存储的val值进行比较&#xff0c;如果不同就返回false&#xff0c;如果全部相同&#xff0c;就返回true。代码&#xff1a;bool _isUni…

傅里叶变换及其应用 pdf_级数的欧拉变换及其应用

前言在学习级数的过程中,读到欧拉变换,觉得非常巧妙,而且在之后发散级数的学习中作者曾提出原级数在发散的情况下欧拉变换后的级数仍有可能收敛(例如1-11-11-...,当然这是Cesaro和意义下的结果或是解析延拓意义下的结果,其级数本身就是发散级数,这是毋庸置疑的,此级数的求和前提…

jpa 参数绑定布尔类型_使用Hibernate JPA的自定义布尔用户类型

jpa 参数绑定布尔类型ANSI SQL 1999标准引入了BOOLEAN数据类型&#xff08;尽管遗憾的是仅作为可选功能&#xff09;。 但是到目前为止&#xff0c;大多数主要的数据库系统仍未实现它。 结果&#xff0c;布尔列以各种方式实现。 例如&#xff0c;包含“ Y”或“ N”的CHAR列&am…

C语言实现面向对象编程 : 封装、继承、多态

点击蓝字关注我们不知道有多少人去了解过语言的发展史&#xff0c;早期C语言的语法功能其实比较简单。随着应用需求和场景的变化&#xff0c;C语言的语法功能在不断升级变化。虽然我们的教材有这么一个结论&#xff1a;C语言是面向过程的语言&#xff0c;C是面向对象的编程语言…

GCC-__attribute__()(一)属性机制

简介 __attribute__((option))是编译器对C语言的扩展&#xff0c;可以设置特定的函数、变量和类型的相关属性。 使用场景 主要用于优化代码&#xff0c;保证编码正确&#xff0c;优化程序逻辑&#xff0c;优化存储格式等&#xff0c;正常简单的项目都没必要使用。 属性列表&a…

python利用什么模块_什么是Python的heapq模块?

我尝试了“heapq”并得出结论,我的期望与我在屏幕上看到的不同.我需要有人解释它是如何工作的以及它在哪里有用. If you need to maintain a sorted list as you add and remove values, check out heapq. By using the functions in heapq to add or remove items from a list…

tomcat默认连接数_Tomcat的默认连接器

tomcat默认连接数Tomcat有几个连接器可供选择。 我将把APR连接器放在一边&#xff0c;而将重点放在BIO和NIO上。 BIO连接器&#xff08;阻塞I / O&#xff09;正在阻塞–它使用线程池&#xff0c;每个线程在该线程池中接收请求&#xff0c;处理请求&#xff0c;响应并返回到该…

图解python pdf_Python合并同一个文件夹下所有PDF文件的方法

一、需求说明 下载了网易云课堂的吴恩达免费的深度学习的pdf文档&#xff0c;但是每一节是一个pdf&#xff0c;我把这些PDF文档放在一个文件夹下&#xff0c;希望合并成一个PDF文件。于是写了一个python程序&#xff0c;很好的解决了这个问题。 二、数据形式三、合并效果四、py…

GCC-编译源文件

一、编译流程 一个C程序从源代码到可执行程序一共有四个过程&#xff1a;预处理->编译->汇编->链接 次序执行流程功能GCC命令1预处理展开头文件、宏替换、去掉注释、条件编译gcc - E main.c - o main.i2编译检查语法&#xff0c;生成汇编程序gcc - S main.i - o mai…

用C语言实现状态机设计模式

点击蓝字关注我们状态机模式是一种行为模式&#xff0c;在 《设计模式》 这本书中对其有详细的描述&#xff0c;通过多态实现不同状态的调转行为的确是一种很好的方法&#xff0c;只可惜在嵌入式环境下&#xff0c;有时只能写纯C代码&#xff0c;并且还需要考虑代码的重入和多任…

python的类是什么意思_Python 各种下划线都是啥意思_、_xx、xx_、__xx、__xx__、_classname_...

我们在定义一些变量或者方法的时候&#xff0c;常常会用到下划线&#xff0c;在 Python 中&#xff0c;下划线可是很有用处的哟&#xff0c;比如变量&#xff0c;有些是一个下划线开头的&#xff08;_xx&#xff09;&#xff0c;有些是两个下划线开头的&#xff08;__xx&#x…