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;效…

这几个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;这就有点方方了。所以我写了一些代码解决实际的问题…

十道题带你手撕二叉树

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

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

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

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

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

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

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

这几行代码,惊为天人!

点击蓝字关注我们事情是这么一回事&#xff1a;国外有个大佬在StackExchange上发起了一个叫做 Tweetable Mathematical Art 的比赛。参赛者需要用C编写代表三原色的RD、GR、BL三个函数&#xff0c;每个函数都不能超过 140 个字符。每个函数都会接到 i 和 j 两个整型参数&#x…

快速搞定C/C++ 的条件编译

点击蓝字关注我们1、条件编译的时机我们都知道vscode其实是一个编辑器&#xff0c;你要在上面跑C或者C你需要配置编译器&#xff0c;拿编译器是怎样吧一个文本文件变成一个可执行文件的呢&#xff1f;那必然是经历以下这四步预处理&#xff1a;宏替换&#xff0c;头文件的展开&…

python连接不上数据库_pycharm连接mysql数据库连接不上

代码其实很简单&#xff0c;只有一小段&#xff0c;是在pycharm上运行的&#xff0c;所用的python版本为2.7&#xff0c;mysql版本为5.7.21 # -*- coding: UTF-8 -*- import re import MySQLdb if __name__ __main__: #打开数据库 conn MySQLdb.connect(hostlocalhost,port33…

assertj_AssertJ的SoftAssertions –我们需要它们吗?

assertj编写好的单元测试的规则之一是&#xff0c;它应该由于一种原因而失败&#xff0c;因此&#xff0c;单元测试应该测试一种逻辑概念。 有时很难在每个测试中拥有一个断言。 为了遵循规则&#xff0c;我们可能在单个测试中每个对象具有多个断言。 但是&#xff0c;在一个测…

用C/C++语言代码实现一个虚拟机

点击蓝字关注我们本文将教你编写一个自己的虚拟机&#xff08;VM&#xff09;&#xff0c;这个虚拟机能够运行汇编语言编写的程序&#xff0c; 例如我朋友编写的 2048 或者我自己的 Roguelike。如果你会编程&#xff0c;但希望 更深入地了解计算机的内部原理以及编程语言是如何…

C++—vector的使用

点击蓝字关注我们一、vector的介绍说的简单点&#xff1a;vector是可以动态增长的数组容器vector是表示可变大小数组的序列容器。就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问&#xff0c;和数组一样高效。…

python词频统计完整步骤_Python中文文本分词、词频统计、词云绘制

本文主要从中文文本分词、词频统计、词云绘制方面介绍Python中文文本分词的使用。会使用到的中文文本处理包包括&#xff1a;wordcloud,jieba&#xff0c;re&#xff08;正则表达式&#xff09;,collections。 1 准备工作 导入相关的包&#xff0c;读取相关数据。 #导入包 impo…

现代 C++ 测试工具链

点击蓝字关注我们gtest的问题gtest需要安装有时候带来很多不方便&#xff0c;比如需要经常切换gcc和clang的时候就比较麻烦&#xff0c;安装的gtest可能在另一个编译器下编译不过, 编写跨平台程序的时候需要多次安装gtest&#xff0c;非常不便。另外一个问题是网络原因&#xf…

数据结构压缩_将数据压缩到数据结构中

数据结构压缩这个故事是关于我们最近在Plumbr进行的容量优化任务。 一切始于将无害的要求添加到现有组合中。 您可能知道&#xff0c;Plumbr监视解决方案作为连接到服务器的Java代理分发。 只需少量添加即可跟踪一段时间内所有已连接的代理&#xff0c;以便可以实时回答以下问…