基本线程同步(七)修改Lock的公平性

修改Lock的公平性

在ReentrantLock类和 ReentrantReadWriteLock类的构造器中,允许一个名为fair的boolean类型参数,它允许你来控制这些类的行为。默认值为 false,这将启用非公平模式。在这个模式中,当有多个线程正在等待一把锁(ReentrantLock或者 ReentrantReadWriteLock),这个锁必须选择它们中间的一个来获得进入临界区,选择任意一个是没有任何标准的。true值将开启公平 模式。在这个模式中,当有多个线程正在等待一把锁(ReentrantLock或者ReentrantReadWriteLock),这个锁必须选择它们 中间的一个来获得进入临界区,它将选择等待时间最长的线程。考虑到之前解释的行为只是使用lock()和unlock()方法。由于tryLock()方 法并不会使线程进入睡眠,即使Lock接口正在被使用,这个公平属性并不会影响它的功能。

在这个指南中,我们将修改使用Lock同步代码块食谱示例来使用这个属性,并且观察公平与非公平模式之间的差别。

准备工作…

我们将要修改使用Lock同步代码块食谱的示例,所以阅读那个食谱来实现这个示例。

如何做…

按以下步骤来实现的这个例子:

1.实现有使用Lock同步代码块食谱中解释的示例。

2.在PrintQueue类,修改Lock对象的构造,如下:

1 private Lock queueLock=new ReentrantLock(true);

3.修改printJob()方法,使用两个代码块分离打印的模拟,在它们之间释放锁。

01 public void printJob(Object document){
02 queueLock.lock();
03 try {
04 Long duration=(long)(Math.random()*10000);
05 System.out.println(Thread.currentThread().getName()+":
06 PrintQueue: Printing a Job during "+(duration/1000)+" seconds");
07 Thread.sleep(duration);
08 } catch (InterruptedException e) {
09 e.printStackTrace();
10 } finally {
11 queueLock.unlock();
12 }
13 queueLock.lock();
14 try {
15 Long duration=(long)(Math.random()*10000);
16 System.out.println(Thread.currentThread().getName()+":
17 PrintQueue: Printing a Job during "+(duration/1000)+" seconds");
18 Thread.sleep(duration);
19 } catch (InterruptedException e) {
20 e.printStackTrace();
21 } finally {
22 queueLock.unlock();
23 }
24 }

4.修改Main类中,启动线程的代码块。新的代码块如下:

1 for (int i=0; i<10; i++){
2 thread[i].start();
3 try {
4 Thread.sleep(100);
5 } catch (InterruptedException e) {
6 e.printStackTrace();
7 }
8 }

它是如何工作的…

在以下截图中,你可以看到执行这个例子的一个部分输出:

所有线程都创建一个0.1秒的差异,第一需要获取锁的控制权的线程是Thread0,然后是Thread1,以此类推。当Thread0正在运行第一个由锁 保护的代码块时,有9个线程正在那个代码块上等待执行。当Thread0释放锁,它需要马上再次获取锁,所以我们有10个线程试图获取这个锁。当启用代码 模式,Lock接口将会选择Thread1,它是在这个锁上等待最长时间的线程。然后,选择Thread2,然后是Thread3,以此类推。直到所有线 程都通过了这个锁保护的第一个代码块,否则,没有一个线程能执行该锁保护的第二个代码块。

一旦所有线程已经执行完由这个锁保护的第一个代码块,再次轮到Thread0。然后,轮到Thread1,以此类推。

为了看与非公平模式的差异,改变传入锁构造器的参数,传入false值。在以下截图中,你可以看到修改示例后的执行结果:

在这种情况下,线程按被创建的顺序执行,但每个线程各自执行两个受保护的代码块。然而,这种行为的原因是没有保证的,正如之前解释的,这个锁将选择任意一个线程获得访问保护代码块。在这种情况下,JVM不能保证线程的执行顺序。

不止这些…

读/写锁在它们的构造器中也有公平参数。这个参数在这种锁中的行为与本指南的解释是一样的。

参见

  • 在第2章,基本线程同步中使用Lock同步代码块的指南
  • 在第2章,基本线程同步中使用读/写锁同步数据访问的指南
  • 在第7章,制订并发类中实现一个自定义的Lock类的指南
时间: 2024-10-22 01:46:14

基本线程同步(七)修改Lock的公平性的相关文章

基本线程同步(一)引言

声明:本文是< Java 7 Concurrency Cookbook >的第二章,作者: Javier Fernández González     译者:许巧辉 校对:方腾飞 引言 在这个章节中,我们将覆盖: 同步方法 在同步的类里安排独立属性 在同步代码中使用条件 使用Lock同步代码块 使用读/写锁同步数据访问  修改Lock的公平性  在Lock中使用多个条件 介绍 在并发编程中发生的最常见的一种情况是超过一个执行线程使用共享资源.在并发应用程序中,多个线程读或写相同的数据或访问同一

基本线程同步(六)使用读/写锁同步数据访问

使用读/写锁同步数据访问 锁所提供的最重要的改进之一就是ReadWriteLock接口和唯一 一个实现它的ReentrantReadWriteLock类.这个类提供两把锁,一把用于读操作和一把用于写操作.同时可以有多个线程执行读操作,但只有一个线程可以执行写操作.当一个线程正在执行一个写操作,不可能有任何线程执行读操作. 在这个指南中,你将会学习如何使用ReadWriteLock接口实现一个程序,使用它来控制访问一个存储两个产品价格的对象. 准备工作- 你应该事先阅读使用Lock同步代码块的指南

[Java] 线程同步的方法:sychronized、lock、reentrantLock分析

版权声明:请尊重个人劳动成果,转载注明出处,谢谢! 如果你向一个变量写值,而这个变量接下来可能会被另一个线程所读取,或者你从一个变量读值,而它的值可能是前面由另一个线程写入的,此时你就必须使用同步. sychronized  Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码,它是在 软件层面依赖JVM实现同步.  synchronized 方法或语句的使用提供了对与每个对象相关的隐式监视器锁的访问,但却强制所有锁获取和释放均要出现在一

c# 线程同步: 详解lock,monitor,同步事件和等待句柄以及mutex

转自 http://www.cnblogs.com/xd125/archive/2007/12/12/992406.html 最近由于在准备Collection对象培训的PPT,因为涉及到SyncRoot的属性的讲解,所以对怎样在多线程应用程序中同步资源访问做了个总结:对于引用类型和非线程安全的资源的同步处理,有四种相关处理:lock关键字,监视器(Monitor), 同步事件和等待句柄, mutex类. Lock关键字    本人愚钝,在以前编程中遇到lock的问题总是使用lock(this)

多线程:C#线程同步lock,Monitor,Mutex,同步事件和等待句柄(下)

转自 http://www.cnblogs.com/freshman0216/archive/2008/08/07/1256919.html    前两篇简单介绍了线程同步lock,Monitor,同步事件EventWaitHandler,互斥体Mutex的基本用法,在此基础上,我们对它们用法进行比较,并给出什么时候需要锁什么时候不需要的几点建议.最后,介绍几个FCL中线程安全的类,集合类的锁定方式等,做为对线程同步系列的完善和补充.       1.几种同步方法的区别       lock和M

线程同步 卖票问题 三个车站卖七张票

问题描述 线程同步 卖票问题 三个车站卖七张票 正确的写法:public class mainclass { public static void main(String[] args) { Train A=new Train(); Train B=new Train(); Train C=new Train(); A.start(); B.start(); C.start(); } } class Train extends Thread{ public static int ticket=7

Windows 8 Store Apps学习(46) 多线程之线程同步: Lock等

多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLock 介绍 重新想象 Windows 8 Store Apps 之 线程同步 lock - 其实就是对 Monitor.Enter() 和 Monitor.Exit() 的一个封装 Monitor - 锁 Interlocked - 为多个线程共享的数字型变量提供原子操作 Mutex - 互斥锁,主要用于同一系统内跨进程的互斥锁 ReaderWriterLock - 读写锁 示例

C#线程同步——lock,Monitor,Mutex(摘录)

线程:线程是进程的独立执行单元,每一个进程都有一个主线程,除了主线程可以包含其他的线程. 多线程的意义:多线程有助于改善程序的总体响应性,提高CPU的效率.       多线程的应用程序域是相当不稳定的,因为多个线程在同一时间内都能运行共享的功能模块.为了保护应用程序的资源不被破坏,为多线程程序提供了三种加锁的机制,分别是:Monitor类.Lock关键字和Mutex类.      1. lock        lock实现的功能是:使后进入的线程不会中断当前的线程,而是等待当前线程结束后再继续

银行取款[多线程]{使用重入锁Lock接口ReentrantLock锁确保线程同步}

经典例子:老婆(朱丽叶)老公(罗密欧),使用银行卡和存折,或者网银等,同时对同一账户操作的安全问题.  此处用多线程实现,同时取款的模拟实现,使用使用Lock接口ReentrantLock锁确保线程同步,查看取款安全隐患问题,代码如下: -----------------------------------------------------------------------------------------------------------------------------------