注:由于要介绍ReentrantLock的东西太多了,免得各位客官看累,所以分三篇博客来阐述。本篇博客介绍ReentrantLock基本内容,后两篇博客从源码级别分别阐述ReentrantLock的lock、unlock实现机制。
ReentrantLock,可重入的互斥锁,是一种递归无阻塞的同步机制。它可以等同于synchronized的使用,但是ReentrantLock提供了比synchronized更强大、灵活的锁机制,可以减少死锁发生的概率。
对于ReentrantLock,官方有详细的说明:一个可重入的互斥锁定 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁定相同的一些基本行为和语义,但功能更强大。ReentrantLock 将由最近成功获得锁定,并且还没有释放该锁定的线程所拥有。当锁定没有被另一个线程所拥有时,调用 lock 的线程将成功获取该锁定并返回。如果当前线程已经拥有该锁定,此方法将立即返回。可以使用 isHeldByCurrentThread() 和 getHoldCount() 方法来检查此情况是否发生。
ReentrantLock提供公平锁机制,构造方法接收一个可选的公平参数。当设置为true时,它是公平锁,这些所将访问权授予等待时间最长的线程。否则该锁将无法保证线程获取锁的访问顺序。但是公平锁与非公平锁相比,公平锁的程序在许多线程访问时表现为很低的总体吞吐量。
/**
* 默认构造方法,非公平锁
*/
public ReentrantLock() {
sync = new NonfairSync();
} /**
* true公平锁,false非公平锁
* @param fair
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
以下是一个简单的使用实例(【java7并发编程实战手册】):
public class PrintQueue {
private final Lock queueLock = new ReentrantLock(); public void printJob(Object document){
try {
queueLock.lock();
System.out.println(Thread.currentThread().getName() + ": Going to print a document");
Long duration = (long) (Math.random() * 10000);
System.out.println(Thread.currentThread().getName() + ":PrintQueue: Printing a Job during " + (duration / 1000) + " seconds");
Thread.sleep(duration);
System.out.printf(Thread.currentThread().getName() + ": The document has been printed\n");
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
queueLock.unlock();
}
}
}
public class Job implements Runnable{ private PrintQueue printQueue; public Job(PrintQueue printQueue){
this.printQueue = printQueue;
} @Override
public void run() {
printQueue.printJob(new Object());
}
}
public class Test {
public static void main(String[] args) {
PrintQueue printQueue = new PrintQueue(); Thread thread[]=new Thread[10];
for (int i = 0; i < 10; i++) {
thread[i] = new Thread(new Job(printQueue), "Thread " + i);
} for(int i = 0 ; i < 10 ; i++){
thread[i].start();
}
}
}
运行结果(部分):
ReentrantLock与synchronized的区别
前面提到ReentrantLock提供了比synchronized更加灵活和强大的锁机制,那么它的灵活和强大之处在哪里呢?他们之间又有什么相异之处呢?
首先他们肯定具有相同的功能和内存语义。
1、与synchronized相比,ReentrantLock提供了更多,更加全面的功能,具备更强的扩展性。例如:时间锁等候,可中断锁等候,锁投票。
2、ReentrantLock还提供了条件Condition,对线程的等待、唤醒操作更加详细和灵活,所以在多个条件变量和高度竞争锁的地方,ReentrantLock更加适合(以后会阐述Condition)。
3、ReentrantLock提供了可轮询的锁请求。它会尝试着去获取锁,如果成功则继续,否则可以等到下次运行时处理,而synchronized则一旦进入锁请求要么成功要么阻塞,所以相比synchronized而言,ReentrantLock会不容易产生死锁些。
4、ReentrantLock支持更加灵活的同步代码块,但是使用synchronized时,只能在同一个synchronized块结构中获取和释放。注:ReentrantLock的锁释放一定要在finally中处理,否则可能会产生严重的后果。
5、ReentrantLock支持中断处理,且性能较synchronized会好些。
敬请关注下篇:【Java并发编程实战】-----“J.U.C”:ReentrantLock之二lock()分析
参考文献:
【Java并发编程实战】-----“J.U.C”:ReentrantLock之一简介的更多相关文章
-
【Java并发编程实战】-----&ldquo;J.U.C&rdquo;:ReentrantLock之三unlock方法分析
前篇博客LZ已经分析了ReentrantLock的lock()实现过程,我们了解到lock实现机制有公平锁和非公平锁,两者的主要区别在于公平锁要按照CLH队列等待获取锁,而非公平锁无视CLH队列直接获 ...
-
【Java并发编程实战】-----“J.U.C”:CountDownlatch
上篇博文([Java并发编程实战]-----"J.U.C":CyclicBarrier)LZ介绍了CyclicBarrier.CyclicBarrier所描述的是"允许一 ...
-
【Java并发编程实战】-----“J.U.C”:CyclicBarrier
在上篇博客([Java并发编程实战]-----"J.U.C":Semaphore)中,LZ介绍了Semaphore,下面LZ介绍CyclicBarrier.在JDK API中是这么 ...
-
【Java并发编程实战】-----&ldquo;J.U.C&rdquo;:ReentrantReadWriteLock
ReentrantLock实现了标准的互斥操作,也就是说在某一时刻只有有一个线程持有锁.ReentrantLock采用这种独占的保守锁直接,在一定程度上减低了吞吐量.在这种情况下任何的"读/ ...
-
【Java并发编程实战】-----&ldquo;J.U.C&rdquo;:Semaphore
信号量Semaphore是一个控制访问多个共享资源的计数器,它本质上是一个"共享锁". Java并发提供了两种加锁模式:共享锁和独占锁.前面LZ介绍的ReentrantLock就是 ...
-
【Java并发编程实战】----- AQS(二):获取锁、释放锁
上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...
-
【Java并发编程实战】----- AQS(四):CLH同步队列
在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形.其主要从两方面进行了改造:节点的结构与节点等待机制.在结构上引入了头 ...
-
【Java并发编程实战】—– AQS(四):CLH同步队列
在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形. 其主要从双方面进行了改造:节点的结构与节点等待机制.在结构上引入了 ...
-
Java并发编程实战 02Java如何解决可见性和有序性问题
摘要 在上一篇文章当中,讲到了CPU缓存导致可见性.线程切换导致了原子性.编译优化导致了有序性问题.那么这篇文章就先解决其中的可见性和有序性问题,引出了今天的主角:Java内存模型(面试并发的时候会经 ...
随机推荐
-
LogBack,升级版的log4J
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE log4j:configuration SYS ...
-
Linq查询操作之Where筛选
筛选操作where能够处理逻辑运算符组成的逻辑表达式.比如逻辑“与”,逻辑“或”,并从数据源中筛选数据,它和where子句的功能非常相似.Enumerable类的Where()原型如下: public ...
-
phonegap/cordova常用命令
创建项目 cordova create foldername com.wps.test projectName cd foldername 基本设备信息 设备 API: cordova plugin ...
-
java split函数 对空的处理
String str = "5,6,55,66,,,,@"; String[] chk_deep = str.split("@"); System.out.pr ...
-
Web应用Word生成
前段时间接到一个Web应用自己主动生成Word的需求,现整理了下一些关键步骤拿来分享一下. 思路:(注:这里仅仅针对WORD2003版本号.其他版本号大同小异.) 由于WORD文件内部的数据及格式等是 ...
-
SQL 查找存储过程及视图与自带函数
查找所有所有存储过程的名称及信息select * from sysobjectswhere type='P' 查看存储过程定义语句sp_helptext [存储过程名] 查看所有视图及信息select ...
-
hdu 3518 Boring counting 后缀数组
题目链接 根据height数组的性质分组计算. #include <iostream> #include <vector> #include <cstdio> #i ...
-
C# 利用 HttpWebRequest 和 HttpWebResponse 模拟登录有验证码的网站
原文:C# 利用 HttpWebRequest 和 HttpWebResponse 模拟登录有验证码的网站 我们经常会碰到需要程序模拟登录一个网站,那如果网站需要填写验证码的要怎样模拟登录呢?这篇文章 ...
-
转-Linux系统下安装rz/sz命令及使用说明
时间: 2013/03/20 | 分类: Linux常用命令 | 作者: 李坏 | 浏览:39,146 | 评论:5 对于经常使用Linux系统的人员来说,少不了将本地的文件上传到服务器或者从服务 ...
-
Objective-C相关Category的收集
Objective-C相关Category的收集 Categories是给你得不到源码的classes增加功能的一种方法.这个页面收集一些相关的Category,并且持续更新,你可以订阅关注.作者是F ...