java的reentrantlock_JAVA中ReentrantLock详解(转)

转自https://www.cnblogs.com/java-learner/p/9651675.html

前言:本文解决的问题

RentrantLock与Synchronized区别

ReentrantLock特征

ReentrantLock类的方法介绍

1.什么是ReentrantLock

1.1ReentrantLock 与Synchronized区别

在面试中询问ReentrantLock与Synchronized区别时,一般回答都是

ReentrantLock

ReentrantLock是JDK方法,需要手动声明上锁和释放锁,因此语法相对复杂些;如果忘记释放锁容易导致死锁

ReentrantLock具有更好的细粒度,可以在ReentrantLock里面设置内部Condititon类,可以实现分组唤醒需要唤醒的线程

RenentrantLock能实现公平锁

Synchronized

Synchoronized语法上简洁方便

Synchoronized是JVM方法,由编辑器保证枷锁和释放

1.2ReentrantLock特征介绍

JAVA的java.util.concurrent框架中提供了ReentrantLock类(于JAVA SE 5.0时引入),ReentrantLock实现了lock接口,具体在JDK中的定义如下:

public class ReentrantLock implements Lock, java.io.Serializable {

public ReentrantLock() {

sync = new NonfairSync();

}

/**

* Creates an instance of {@code ReentrantLock} with the

* given fairness policy.

*

* @param fair {@code true} if this lock should use a fair ordering policy

*/

public ReentrantLock(boolean fair) {

sync = fair ? new FairSync() : new NonfairSync();

}

}

看到一个类首先就需要知道它的构造方法有哪些,ReentrantLock有两个构造方法,一个是无参的 ReentrantLock();另一个含有布尔参数public ReentrantLock(boolean fair)。后面一个构造函数说明ReentrantLock可以新建公平锁;而Synchronized只能建立非公平锁。

那么Lock接口有哪些方法

8031577c1ff95a7f4e292c3baebd0fa4.png

Lock接口中有lock和unlock方法,还有newCondition() 方法,这就是上面说的ReentrantLock里面设置内部Condititon类。由于ReentrantLock实现了Lock接口,因此它必须实现该方法,具体如下:

public Condition newCondition() {

return sync.newCondition();

}

返回Condition类的一个实例。

2 ReentrantLock其它方法介绍

在介绍它的其它方法前,要先明白它的使用方法,以下JDK中的建议:

class X {

private final ReentrantLock lock = new ReentrantLock();

// ...

public void m() {

lock.lock(); // block until condition holds

try {

// ... method body

} finally {

lock.unlock()

}

}

建议用try,在finally里面一定要释放锁,防止被中断时锁没释放,造成死锁

lock()

public void lock() {

sync.lock();

}

如果该锁没被其它线程获得,则立即返回;并且把 lock hold count的值变位1.

unlock()

public void unlock() {

sync.release(1);

}

如果当前线程是该锁的持有者,则保持计数递减。 如果保持计数现在为零,则锁定被释放。 如果当前线程不是该锁的持有者,则抛出IllegalMonitorStateException 。

isFair()

public final boolean isFair() {

return sync instanceof FairSync;

}

判断该锁是不是公平锁

newCondition()

public Condition newCondition() {

return sync.newCondition();

}

返回新的ConditionObject对象。

Condition接口中的方法

await(): void await() throws InterruptedException;

Condition接口中的方法,导致当前线程等到发信号。

siginal()

/**

* Moves the longest-waiting thread, if one exists, from the

* wait queue for this condition to the wait queue for the

* owning lock.

*

* @throws IllegalMonitorStateException if {@link #isHeldExclusively}

* returns {@code false}

*/

public final void signal() {

if (!isHeldExclusively())

throw new IllegalMonitorStateException();

Node first = firstWaiter;

if (first != null)

doSignal(first);

}

唤醒一个等待该条件的线程去获得锁(第一个)。

signalAll():唤醒所有等待线程。

3 ReentrantLock完整实例介绍

package chapter10.reentrantlock;

import java.util.Arrays;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

/*模拟转账,把钱从一个账户转到另一个账户

* */

public class ReentrantLockUse {

public static final int NACCOUNTS = 100;

public static final double INITIAL_BALANCE = 1000;

public static final double MAX_AMOUNT = 1000;

public static final int DELAY = 10;

public static void main(String[] args) {

Bank bank = new Bank(NACCOUNTS,INITIAL_BALANCE);

for(int i = 0 ; i < NACCOUNTS ; i++) {

int fromAccount = i ;

Runnable r = () ->{//lambda表达式

try {

while(true) {

int toAccount = (int) (bank.size()*Math.random());

double amount = MAX_AMOUNT * Math.random();

bank.transfer(fromAccount, toAccount, amount);

Thread.sleep((int)(DELAY*Math.random()));

}

}

catch(InterruptedException e) {

}

};

Thread t = new Thread(r);//新建线程

t.start();

}

}

}

class Bank{

private final double[] account;//账户

private Lock bankLock ; //重复锁

private Condition sufficientFunds; //条件对象

public Bank(int n, double initialBalance) {

account = new double[n];

Arrays.fill(account, initialBalance);

bankLock = new ReentrantLock(); //构造对象时,实例化锁

sufficientFunds = bankLock.newCondition();//新建条件对象

}

/*转账,把from账户里面的钱转到to里面,金额是amount*/

public void transfer(int from , int to,double amount) {

bankLock.lock();

try {

while(account[from] < amount) {

sufficientFunds.await();

}

System.out.println(Thread.currentThread());

account[from] -=amount;

System.out.printf("%10.2f from %d to %d ",amount,from,to);

account[to] +=amount;

System.out.printf(" Total Balance : %10.2f%n", getTotalBalance());

sufficientFunds.signalAll();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

finally {

bankLock.unlock();

}

}

/*做的所有账户总额*/

public double getTotalBalance() {

bankLock.lock();

try {

double sum = 0;

for(double a : account) {

sum +=a;

}

return sum;

}

finally {

bankLock.unlock();

}

}

public int size() {

return account.length;

}

}

执行结果

96e599f9bbf2877ca619aca1fdfec391.png

结果分析

循环建立100个线程,每个线程都在不停转账,由于ReentrantLock的使用,任何时刻所有账户的总额都保持不变。另外,把钱amount从A账户转到B账户,要先判断A账户中是否有这么多钱,不过没有就调用条件对象ConditionObject中的await()方法,放弃该线程,等该其它线程转钱进来;转钱完成后调用.siginalAll()。

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

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

相关文章

Servlet添加商品

Servlet实现添加商品 <% page language"java" contentType"text/html; charsetUTF-8"pageEncoding"UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd&…

java运行win10_win10配置java运行环境

1.下载jdk根据自己的电脑下载对应的版本&#xff0c;需要先注册账号才可以下载百度网盘&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1gjpdQo8t8Va8uPiHDDvB3Q提取码&#xff1a;5a0c2.下载完成&#xff0c;点击安装&#xff0c;一般直接根据默认安装即可&#xff0c;…

[转]C#网络编程(同步传输字符串) - Part.2

本文转自&#xff1a;http://www.tracefact.net/CSharp-Programming/Network-Programming-Part2.aspx 服务端客户端通信 在与服务端的连接建立以后&#xff0c;我们就可以通过此连接来发送和接收数据。端口与端口之间以流&#xff08;Stream&#xff09;的形式传输数据&#xf…

tomcat 设置java_为tomcat配置java环境变量

我的tomcat 中java标签里是这么写的java virual Machine:C:\Program Files\Java\jre1.6.0\bin\client\jvm.dlljava classpath:C:\Program Files\Apache Software Foundation\Tomcat 5.5\bin\bootstrap.jarjava options:-Dcatalina.homeC:\Program Files\Apache Software Founda…

项目开发流程标准

1 项目各阶段主要成果列表 项目阶段 主要内容 1、商务谈判阶段 《业务需求说明书》、《项目风险评估报告》、 《项目可行性报告书》&#xff08;可由市场或TC部提供&#xff09; 或1、技术部项目立项 《技术部项目立项表》、《项目可行性报告书》 2、计划与设计阶…

java servlet 3_java – Servlet 2.5和3之间有什么区别?

更新正如一个更新和更明确&#xff0c;这些是servlet 2.5和3之间的主要区别(我不想穷举&#xff0c;我只是提到最有趣的部分)&#xff1a;声明servlet&#xff0c;过滤器和监听器的注释(易于开发)在servlets 2.5中&#xff0c;要声明具有一个init参数的servlet&#xff0c;您需…

python 内置模块-re

想要在python中使用正则表达式&#xff0c;就需要先导入re模块&#xff0c;正则表达式是一个强大的功能&#xff0c;可以为我们节省很多工作量。 一、元字符&#xff1a; 用一些具有特殊含义的符号表示特定种类的字符或位置。. 匹配除换行符以外的任意字符\w匹配字母或数字或下…

java8 stringbuilder_为什么 Java 8 中不需要 StringBuilder 拼接字符串

在Java开发者中&#xff0c;字符串的拼接占用资源高往往是热议的话题.让我们深入讨论一下为什么会占用高资源。在Java中&#xff0c;字符串对象是不可变的&#xff0c;意思是它一旦创建&#xff0c;你就无法再改变它。所以在我们拼接字符串的时候&#xff0c;创建了一个新的字符…

js函数引用、函数调用与回调函数

var function1function2; 1.调用function1()函数的结果正好与调用function2()相同&#xff0c;因为两个函数都引用了相同的代码&#xff0c;因此函数名称也称为函数调用。 2.引用函数与调用函数的区别与函数名称后是否附有括号有关&#xff0c;函数引用只会单独出现&#xff0c…

c mysql dll_C:\Windows\libmysql_e.dll

这是C:\Windows\libmysql_e.dll下载&#xff0c;一款很重要的dll文件组件哦&#xff0c;如果你的电脑libmysql e.dll错误或者确实会导致很程序和软件都不能正常运行的哦&#xff0c;有需要的就来下载吧&#xff01;软件介绍C:\Windows\libmysql_e.dll是需要安装php和MySQL的工具…

FileInputStream 把文件作为字节流进行读操作

//把文件作为字节流进行读操作 FileInputStream in new FileInputStream(filename);//FileInputStream具体实现了在文件上读取数据转载于:https://www.cnblogs.com/xuedexin/p/5639327.html

java datetime 转换_如何实现Java日期时间格式转换

Java日期时间以及日期相互转换Java日期时间&#xff0c;以及相互转化&#xff0c;供大家参考&#xff0c;具体内容如下package com.study.string;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.Date;import …

Mac 使用常见问题汇集

1、Mac系统如何隐藏文件或文件夹&#xff1f; 在 Mac 文件的文件名前添加 . 即可使文件隐藏 2、Mac系统如何查看隐藏文件&#xff1f; 终端里面能用命令来控制: 显示Mac隐藏文件的命令&#xff1a;defaults write com.apple.finder AppleShowAllFiles YES 隐藏Mac隐藏文件的命令…

安卓手机的a/span的宽高失效

最近在做一个移动端的项目&#xff0c;网页版 在IOS上显示都是妥妥的&#xff0c;可是一部华为中的UC浏览器的效果就让人傻眼了&#xff0c;好多按钮都是都缩在一起&#xff0c;宽高失效。 折腾了半天找不到蛛丝马迹&#xff0c;最后实验发现<a><span>在华为手机中…

java model 封装_Java封装统一的Result Model案例

在开发过程中&#xff0c;有时候会需要使用错误码错误信息的形式&#xff0c;来返回某些业务操作的错误结果信息&#xff0c;来代替效率较低的异常传递。这样就需要封装一个统一的Result model作为返回值&#xff0c;代替直接返回数据等结果。1.定义错误码 - 错误信息接口错误码…

java 日期随机数_Java 生成指定时间范围的随机时间、随机中文姓名、随机字符姓名、随机数...

解决问题&#xff1a;Java生成指定时间范围的随机时间&#xff1f;Java生成随机中文姓名&#xff1f;Java生成随机字符姓名&#xff1f;Java生成随机数&#xff1f;代码&#xff1a;import java.io.UnsupportedEncodingException;import java.text.ParseException;import java.…

java语言程序设计基础篇14.6答案_《Java语言程序设计-基础篇》答案-第15章

第15章 异常和断言复习题15.1 答&#xff1a;略15.2 答&#xff1a;声明异常是为了在方法中产生异常时&#xff0c;以便通知方法的调用者。在方法声明的头部使用关键字throws 声明&#xff0c;一个方法可以声明多个异常。如&#xff1a;public void method() throws IOExceptio…

《机器学习》周志华 习题答案9.4

原题采用Kmeans方法对西瓜数据集进行聚类。我花了一些时间居然没找到西瓜数据集4.0在哪里&#xff0c;于是直接采用sklearn给的例子来分析一遍&#xff0c;更能说明Kmeans的效果。 #!/usr/bin/python # -*- coding:utf-8 -*- import numpy as np import matplotlib.pyplot as p…

一个电商项目的功能模块梳理

电商项目核心玩法&#xff1a;定制商品供应链&#xff08;商品辅料库&#xff09;网红社区最近做项目&#xff0c;功能越来越多&#xff0c;想清晰地理解项目&#xff0c;有点累了。今天抽空&#xff0c;把这个项目的核心功能模块简要总结下&#xff0c;顺便画了个图。一、全局…

java8 循环jsonarray_JSONArray 遍历方式

第一种(java8):遍历JSONArray 拼接字符串 public static void main(String[] args) {JSONArray jSONArray = new JSONArray(); JSONObject jb = new JSONObject(); jb.put("id", 1); jb.put("name", "s"); jSONArray.add(jb); JSONObject j1 = …