Java中的Lock锁
Lock锁介绍:
在java中可以使用 synchronized 来实现多线程下对象的同步访问,为了获得更加灵活使用场景、高效的性能,java还提供了Lock接口及其实现类ReentrantLock和读写锁 ReentrantReadWriteLock。
相比synchronized来实现同步,使用Lock实现同步主要有以下差异性:
1、使用synchronized关键字时,锁的控制和释放是在synchronized同步代码块的开始和结束位置。而在使用Lock实现同步时,锁的获取和释放可以在不同的代码块、不同的方法中。这一点是基于使用者手动获取和释放锁的特性。
2、Lock接口提供了试图获取锁的tryLock()方法,在调用tryLock()获取锁失败时返回false,这样线程可以执行其它的操作 而不至于使线程进入休眠。tryLock()方法可传入一个long型的时间参数,允许在一定的时间内来获取锁。
3、Lock接口的实现类ReentrantReadWriteLock提供了读锁和写锁,允许多个线程获得读锁、而只能有一个线程获得写锁。读锁和写锁不能同时获得。实现了读和写的分离,这一点在需要并发读的应用中非常重要,如lucene允许多个线程读取索引数据进行查询但只能有一个线程负责索引数据的构建。
4、基于以上3点,lock来实现同步具备更好的性能。
Lock锁与条件同步:
与synchronized类似,Lock锁也可以实现条件同步。在java的concurrent包中提供了 Condition 接口及其实现类ConditionObject。
当满足一定条件时,调用Condition的await()方法使当前线程进入休眠状态进行等待。调用Condition的signalAll()方法唤醒因await()进入休眠的线程。
在synchronized与条件同步博文中,我们使用synchronized实现了一个生产者-消费者模型,在这里,来试试使用Lock锁及其同步条件来实现同样的一个生产者-消费者模型:
public class MessageStorageByLock {
private int maxSize;
private List<String> messages;
private final ReentrantLock lock;
private final Condition conditionWrite;//声明两个锁条件
private final Condition conditionRead;
public MessageStorageByLock(int maxSize) {
this.maxSize = maxSize;
messages = new LinkedList<String>();
lock = new ReentrantLock(true);//true修改锁的公平性,为true时,使用lifo队列来顺序获得锁
conditionWrite = lock.newCondition();//调用newCondition()方法,即new ConditionObject();
conditionRead = lock.newCondition();
}
public void set(String message){
//使用锁实现同步,获取所得操作,当锁被其他线程占用时,当前线程将进入休眠
lock.lock();
try{
while(messages.size() == maxSize){
System.out.print("the message buffer is full now,start into wait()\n");
conditionWrite.await();//满足条件时,线程休眠并释放锁。当调用 signalAll()时。线程唤醒并重新获得锁
}
Thread.sleep(100);
messages.add(message);
System.out.print("add message:"+message+" success\n");
conditionRead.signalAll();//唤醒因conditionRead.await()休眠的线程
}catch (InterruptedException e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public String get(){
String message = null;
lock.lock();
try{
while(messages.size() == 0){
conditionRead.await();
System.out.print("the message buffer is empty now,start into wait()\n");
}
Thread.sleep(100);
message = ((LinkedList<String>)messages).poll();
System.out.print("get message:"+message+" success\n");
conditionWrite.signalAll();
}catch (InterruptedException e){
e.printStackTrace();
}finally {
lock.unlock();
}
return message;
}
}
总结:
不管是synchronized关键字还是Lock锁,都是用来在多线程的环境下对资源的同步访问进行控制,用以避免因多个线程对数据的并发读写造成的数据混乱问题。与synchronized不同的是,Lock锁实现同步时需要使用者手动控制锁的获取和释放,其灵活性使得可以实现更复杂的多线程同步和更高的性能,但同时,使用者一定要在获取锁后及时捕获代码运行过程中的异常并在finally代码块中释放锁。
Java中的Lock锁的更多相关文章
- 一文带你看懂Java中的Lock锁底层AQS到底是如何实现的
前言 相信大家对Java中的Lock锁应该不会陌生,比如ReentrantLock,锁主要是用来解决解决多线程运行访问共享资源时的线程安全问题.那你是不是很好奇,这些Lock锁api是如何实现的呢?本 ...
- 分门别类总结Java中的各种锁,让你彻底记住
概念 公平锁/非公平锁 公平锁是指多个线程按照申请锁的顺序来获取锁. 非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁.有可能,会造成优先级反转或者饥 ...
- Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等
Java 中15种锁的介绍 Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等,在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类 ...
- Java中的各种锁--分类总结
前言 本文需要具备一定的多线程基础才能更好的理解. 学习java多线程时,最头疼的知识点之一就是java中的锁了,什么互斥锁.排它锁.自旋锁.死锁.活锁等等,细分的话可以罗列出20种左右的锁,光是看着 ...
- 轻松搞懂Java中的自旋锁
前言 在之前的文章<一文彻底搞懂面试中常问的各种“锁”>中介绍了Java中的各种“锁”,可能对于不是很了解这些概念的同学来说会觉得有点绕,所以我决定拆分出来,逐步详细的介绍一下这些锁的来龙 ...
- Java中15种锁的分类综合总结
本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...
- Java 中的各种锁和 CAS + 面试题
Java 中的各种锁和 CAS + 面试题 如果说快速理解多线程有什么捷径的话,那本文介绍的各种锁无疑是其中之一,它不但为我们开发多线程程序提供理论支持,还是面试中经常被问到的核心面试题之一.因此下面 ...
- Java中15种锁的介绍
作者:搜云库技术团队 原文:https://segmentfault.com/a/1190000017766364 1. Java 中15种锁的介绍 在读很多并发文章中,会提及各种各样锁如公平锁,乐观 ...
- 在 Java 中高效使用锁的技巧--转载
竞争锁是造成多线程应用程序性能瓶颈的主要原因 区分竞争锁和非竞争锁对性能的影响非常重要.如果一个锁自始至终只被一个线程使用,那么 JVM 有能力优化它带来的绝大部分损耗.如果一个锁被多个线程使用过,但 ...
随机推荐
- angularJs-route路由详解
本篇基于ng-route来讲下angular中的路由,路由功能主要是 $routeProvider服务 与 ng-view 实现. ng-view的实现原理,是根据路由的切换,动态编译html模板-- ...
- html5之表格元素
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- c++简单线程池实现
线程池,简单来说就是有一堆已经创建好的线程(最大数目一定),初始时他们都处于空闲状态,当有新的任务进来,从线程池中取出一个空闲的线程处理任务,然后当任务处理完成之后,该线程被重新放回到线程池中,供其他 ...
- javaScript系列 [04]-javaScript的原型链
[04]-javaScript的原型链 本文旨在花很少的篇幅讲清楚JavaScript语言中的原型链结构,很多朋友认为JavaScript中的原型链复杂难懂,其实不然,它们就像树上的一串猴子. 1.1 ...
- [BJOI 2011]元素
Description 相传,在远古时期,位于西方大陆的 Magic Land 上,人们已经掌握了用魔法矿石炼制法杖的技术.那时人们就认识到,一个法杖的法力取决于使用的矿石.一般地,矿石越多则法力越强 ...
- [Luogu 3902]Increasing
Description Input Output Sample Input 3 1 3 2 Sample Output 1 HINT 题解 由于题目要求我们求严格递增的数列,即: $$A[i]> ...
- [SDOI2014]重建
题目描述 T国有N个城市,用若干双向道路连接.一对城市之间至多存在一条道路. 在一次洪水之后,一些道路受损无法通行.虽然已经有人开始调查道路的损毁情况,但直到现在几乎没有消息传回. 辛运的是,此前T国 ...
- 洛谷mNOIP模拟赛Day2-星空
题目背景 pdf题面和大样例链接:http://pan.baidu.com/s/1cawM7c 密码:xgxv 命运偷走如果只留下结果, 时间偷走初衷只留下了苦衷. 你来过,然后你走后,只留下星空. ...
- SPOJ Coconuts 最大流 最小割
A group of n castle guards are voting to determine whether African swallows can carry coconuts. Whil ...
- Python-闭包详解
在函数编程中经常用到闭包.闭包是什么,它是怎么产生的及用来解决什么问题呢.给出字面的定义先:闭包是由函数及其相关的引用环境组合而成的实体(即:闭包=函数+引用环境)(想想Erlang的外层函数传入一个 ...