ReentrantLock和ReentrantReadWriteLock类的构造函数可接受一个布尔类型参数fair,表示你可以控制这2个类的行为。

其默认值为false,代表non-fair(不公平)模式。

这种模式下,如果有多个线程等待获得锁并且只能有一个线程获得,上面2个锁类会无条件选择一个。(也就是随机抽一个)

值为true的话就表示fair模式,即公平模式。

意思是有个先来后到,就跟咱们买东西要排队一样。锁会分给那个等了最长时间的线程。





以上逻辑仅适用于lock() and unlock()方法。因为例如tryLock()方法压根不会让线程睡眠。

本例中,我们将修改一下之前使用锁机制同步代码块的程序,加入这个参数来对比一下fair和non-fair两种模式的差别。

PrintQueue.java
package com.dylan.thread.ch2.c06.task;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
* This class simulates a print queue.
*
*/
public class PrintQueue { /**
* Creates a lock to control the access to the queue.
* With the boolean attribute, we control the fairness of
* the Lock
*/
private final Lock queueLock=new ReentrantLock(false); /**
* Method that prints the Job. The printing is divided in two phase two
* show how the fairness attribute affects the election of the thread who
* has the control of the lock
* @param document The document to print
*/
public void printJob(Object document){
queueLock.lock(); try {
Long duration=(long)(Math.random()*10000);
System.out.printf("%s: PrintQueue: Printing a Job during %d seconds\n",Thread.currentThread().getName(),(duration/1000));
Thread.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
queueLock.unlock();
} queueLock.lock();
try {
Long duration=(long)(Math.random()*10000);
System.out.printf("%s: PrintQueue: Printing a Job during %d seconds\n",Thread.currentThread().getName(),(duration/1000));
Thread.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
queueLock.unlock();
}
}
}
Job.java
package com.dylan.thread.ch2.c06.task;

/**
* This class simulates a job that send a document to print
*
*/
public class Job implements Runnable { /**
* The queue to send the documents
*/
private PrintQueue printQueue; /**
* Constructor of the class. Initializes the print queue
* @param printQueue the print queue to send the documents
*/
public Job(PrintQueue printQueue){
this.printQueue=printQueue;
} /**
* Core method of the Job. Sends the document to the queue
*/
@Override
public void run() {
System.out.printf("%s: Going to print a job\n",Thread.currentThread().getName());
printQueue.printJob(new Object());
System.out.printf("%s: The document has been printed\n",Thread.currentThread().getName());
} }
Main.java
package com.dylan.thread.ch2.c06.core;

import com.dylan.thread.ch2.c06.task.Job;
import com.dylan.thread.ch2.c06.task.PrintQueue; /**
* Main class of the example
*
*/
public class Main { /**
* Main method of the example
* @param args
*/
public static void main (String args[]){
// Creates the print queue
PrintQueue printQueue=new PrintQueue(); // Cretes ten jobs and the Threads to run them
Thread thread[]=new Thread[10];
for (int i=0; i<10; i++){
thread[i]=new Thread(new Job(printQueue),"Thread "+i);
} // Launch a thread ever 0.1 seconds
for (int i=0; i<10; i++){
thread[i].start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} }

运行结果:

1.不公平模式:

Thread 0: Going to print a job
Thread 0: PrintQueue: Printing a Job during 0 seconds
Thread 1: Going to print a job
Thread 2: Going to print a job
Thread 3: Going to print a job
Thread 4: Going to print a job
Thread 5: Going to print a job
Thread 6: Going to print a job
Thread 0: PrintQueue: Printing a Job during 1 seconds
Thread 7: Going to print a job
Thread 8: Going to print a job
Thread 9: Going to print a job
Thread 1: PrintQueue: Printing a Job during 1 seconds
Thread 0: The document has been printed
Thread 1: PrintQueue: Printing a Job during 8 seconds
Thread 1: The document has been printed
Thread 2: PrintQueue: Printing a Job during 3 seconds
Thread 2: PrintQueue: Printing a Job during 8 seconds
Thread 2: The document has been printed
Thread 3: PrintQueue: Printing a Job during 6 seconds
Thread 3: PrintQueue: Printing a Job during 5 seconds
Thread 3: The document has been printed
Thread 4: PrintQueue: Printing a Job during 9 seconds
Thread 5: PrintQueue: Printing a Job during 3 seconds
Thread 5: PrintQueue: Printing a Job during 1 seconds
Thread 6: PrintQueue: Printing a Job during 1 seconds
Thread 5: The document has been printed
Thread 6: PrintQueue: Printing a Job during 6 seconds
Thread 6: The document has been printed
Thread 7: PrintQueue: Printing a Job during 8 seconds
Thread 7: PrintQueue: Printing a Job during 5 seconds
Thread 7: The document has been printed
Thread 8: PrintQueue: Printing a Job during 7 seconds
Thread 8: PrintQueue: Printing a Job during 5 seconds
Thread 8: The document has been printed
Thread 9: PrintQueue: Printing a Job during 1 seconds
Thread 9: PrintQueue: Printing a Job during 3 seconds
Thread 9: The document has been printed
Thread 4: PrintQueue: Printing a Job during 7 seconds
Thread 4: The document has been printed

2.公平模式:

Thread 0: Going to print a job
Thread 0: PrintQueue: Printing a Job during 1 seconds
Thread 1: Going to print a job
Thread 2: Going to print a job
Thread 3: Going to print a job
Thread 4: Going to print a job
Thread 5: Going to print a job
Thread 6: Going to print a job
Thread 7: Going to print a job
Thread 8: Going to print a job
Thread 9: Going to print a job
Thread 1: PrintQueue: Printing a Job during 8 seconds
Thread 2: PrintQueue: Printing a Job during 9 seconds
Thread 3: PrintQueue: Printing a Job during 0 seconds
Thread 4: PrintQueue: Printing a Job during 3 seconds
Thread 5: PrintQueue: Printing a Job during 1 seconds
Thread 6: PrintQueue: Printing a Job during 0 seconds
Thread 7: PrintQueue: Printing a Job during 7 seconds
Thread 8: PrintQueue: Printing a Job during 3 seconds
Thread 9: PrintQueue: Printing a Job during 4 seconds
Thread 0: PrintQueue: Printing a Job during 6 seconds
Thread 0: The document has been printed
Thread 1: PrintQueue: Printing a Job during 9 seconds
Thread 1: The document has been printed
Thread 2: PrintQueue: Printing a Job during 4 seconds
Thread 2: The document has been printed
Thread 3: PrintQueue: Printing a Job during 3 seconds
Thread 3: The document has been printed
Thread 4: PrintQueue: Printing a Job during 1 seconds
Thread 5: PrintQueue: Printing a Job during 3 seconds
Thread 4: The document has been printed
Thread 5: The document has been printed
Thread 6: PrintQueue: Printing a Job during 0 seconds
Thread 6: The document has been printed
Thread 7: PrintQueue: Printing a Job during 0 seconds
Thread 7: The document has been printed
Thread 8: PrintQueue: Printing a Job during 3 seconds
Thread 9: PrintQueue: Printing a Job during 1 seconds
Thread 8: The document has been printed
Thread 9: The document has been printed

Java并发编程实例--18.修改锁的公平性的更多相关文章

  1. Java并发编程实战 03互斥锁 解决原子性问题

    文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 摘要 在上一篇文章02Java如何解决可见性和有序性问题当中,我们解决了可见性和 ...

  2. Java并发编程:线程和锁的使用与解析

    线程的使用  新建线程 新建一个线程有两种方法:继承Thread类,然后重写run方法:实现Runnable接口,然后实现run方法.实际上Thread类也是实现的Runnable接口,再加上类只能单 ...

  3. Java并发编程(05):悲观锁和乐观锁机制

    本文源码:GitHub·点这里 || GitEE·点这里 一.资源和加锁 1.场景描述 多线程并发访问同一个资源问题,假如线程A获取变量之后修改变量值,线程C在此时也获取变量值并且修改,两个线程同时并 ...

  4. Java并发编程:Lock(锁)

    一.synchronized的缺陷 synchronized是java中的一个关键字,也就是说是Java语言内置的特性.那么为什么会出现Lock呢? 在上面一篇文章中,我们了解到如果一个代码块被syn ...

  5. Java并发编程笔记之StampedLock锁源码探究

    StampedLock是JUC并发包里面JDK1.8版本新增的一个锁,该锁提供了三种模式的读写控制,当调用获取锁的系列函数的时候,会返回一个long 型的变量,该变量被称为戳记(stamp),这个戳记 ...

  6. Java并发编程-可重入锁

    可重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍可以获取该锁而不受影响.在JAVA环境下 ReentrantLock 和synchronized 都是 可重入锁. publ ...

  7. Java并发编程实例(synchronized)

    此处用一个小程序来说明一下,逻辑是一个计数器(int i):主要的逻辑功能是,如果同步监视了资源i,则不输出i的值,但如果没有添加关键字synchronized,因为是两个线程并发执行,所以会输出i的 ...

  8. Java并发编程(五)锁的使用(下)

    显式锁 上篇讲了使用synchronized关键字来定义锁,其实Java除了使用这个关键字外还可以使用Lock接口及其实现的子类来定义锁,ReentrantLock类是Lock接口的一个实现,Reen ...

  9. Java并发编程:synchronized和锁优化

    1. 使用方法 synchronized 是 java 中最常用的保证线程安全的方式,synchronized 的作用主要有三方面: 确保线程互斥的访问代码块,同一时刻只有一个方法可以进入到临界区 保 ...

  10. Java并发编程之显式锁机制

    我们之前介绍过synchronized关键字实现程序的原子性操作,它的内部也是一种加锁和解锁机制,是一种声明式的编程方式,我们只需要对方法或者代码块进行声明,Java内部帮我们在调用方法之前和结束时加 ...

随机推荐

  1. Oracle19c 多字符集支持的PDB

    Oracle19c 多字符集支持的PDB 背景 想在一个数据库里面支持多种字符集 突然发现Oracle12c开始已经可以实现一个CDB下面可以有多个不同字符集的PDB了 所以想着今天验证一下. 环境信 ...

  2. tikv-ctl的简单学习

    tikv-ctl的简单学习 摘要 最近在学习使用 tidb. 有一个场景,单独使用了tikv作为键值对的数据库. 但是比较不幸.总是出现宕机的情况 因为这个环境是单独使用tikv 二进制进行安装的 没 ...

  3. [转帖]Skip List--跳表(全网最详细的跳表文章没有之一)

    https://www.jianshu.com/p/9d8296562806 跳表是一种神奇的数据结构,因为几乎所有版本的大学本科教材上都没有跳表这种数据结构,而且神书<算法导论>.< ...

  4. [转帖] Linux命令拾遗-查看系统信息

    https://www.cnblogs.com/codelogs/p/16060714.html 简介# 作为一名程序员,有时需要关注自己的进程运行在什么样的软硬件环境里,比如几核cpu.固态硬盘还是 ...

  5. 【转帖】python 安装whl文件

    前言 WHL文件是以Wheel格式保存的Python安装包,Wheel是Python发行版的标准内置包格式.在本质上是一个压缩包,WHL文件中包含了Python安装的py文件和元数据,以及经过编译的p ...

  6. [转帖]RPC 框架总结与进阶

    https://www.cnblogs.com/xiaojiesir/p/15579418.html 框架总结 Netty 服务端启动 Netty 提供了 ServerBootstrap 引导类作为程 ...

  7. 是否开启超线程对CPU不同命令的影响情况

    背景 最近公司购买了一台服务器, 要进行一次性能测试. 基于此, 我这边进行了一下超线程与否的测试验证 使用stress-ng的命令,对所有的 CPU 方法进行测试 然后只分析 bogo ops/s ...

  8. buildkit 官网 service 资料

    [Unit]   Description=BuildKit   Requires=buildkit.socket   After=buildkit.socket   Documentation=htt ...

  9. Semantic Kernel 通过 LocalAI 集成本地模型

    本文是基于 LLama 2是由Meta 开源的大语言模型,通过LocalAI 来集成LLama2 来演示Semantic kernel(简称SK) 和 本地大模型的集成示例. SK 可以支持各种大模型 ...

  10. OpenIM (Open-Source Instant Messaging) Mac Deployment Guide

    This guide provides step-by-step instructions for deploying OpenIM on a Mac, including both source c ...