Java中的Lock锁

时间:2022-09-02 14:00:25

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锁的更多相关文章

  1. 分门别类总结Java中的各种锁,让你彻底记住

    概念 公平锁/非公平锁 公平锁是指多个线程按照申请锁的顺序来获取锁. 非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁.有可能,会造成优先级反转或者饥 ...

  2. Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等

    Java 中15种锁的介绍 Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等,在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类 ...

  3. Java中的各种锁--分类总结

    前言 本文需要具备一定的多线程基础才能更好的理解. 学习java多线程时,最头疼的知识点之一就是java中的锁了,什么互斥锁.排它锁.自旋锁.死锁.活锁等等,细分的话可以罗列出20种左右的锁,光是看着 ...

  4. 轻松搞懂Java中的自旋锁

    前言 在之前的文章<一文彻底搞懂面试中常问的各种“锁”>中介绍了Java中的各种“锁”,可能对于不是很了解这些概念的同学来说会觉得有点绕,所以我决定拆分出来,逐步详细的介绍一下这些锁的来龙 ...

  5. Java中15种锁的分类综合总结

    本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...

  6. Java 中的各种锁和 CAS &plus; 面试题

    Java 中的各种锁和 CAS + 面试题 如果说快速理解多线程有什么捷径的话,那本文介绍的各种锁无疑是其中之一,它不但为我们开发多线程程序提供理论支持,还是面试中经常被问到的核心面试题之一.因此下面 ...

  7. Java中15种锁的介绍

    作者:搜云库技术团队 原文:https://segmentfault.com/a/1190000017766364 1. Java 中15种锁的介绍 在读很多并发文章中,会提及各种各样锁如公平锁,乐观 ...

  8. 在 Java 中高效使用锁的技巧--转载

    竞争锁是造成多线程应用程序性能瓶颈的主要原因 区分竞争锁和非竞争锁对性能的影响非常重要.如果一个锁自始至终只被一个线程使用,那么 JVM 有能力优化它带来的绝大部分损耗.如果一个锁被多个线程使用过,但 ...

  9. Java中的Lock与synchronized

    并发编程学习笔记之Lock与synchronized 一.什么是可重入锁 Lcok在Java中是一个接口,一般在面试问题中问到的可能是ReentrantLock与synchronized的区别.Ree ...

随机推荐

  1. C&sol;C&plus;&plus;二维数组的用法

    二维数组在存储时按行优先连续存储,数组名是一个二维指针,如 int a[3][2] 中,a 是一个二维指针,而a[0],a[1],a[2]都相当于普通的一位数组的数组名,是一个固定值的指针. 二维数组 ...

  2. 程序中的&commat;Override是什么意思

    @Override是Java5的元数据,自动加上去的一个标志,告诉你说下面这个方法是从父类/接口 继承过来的,需要你重写一次,这样就可以方便你阅读,也不怕会忘记 @Override是伪代码,表示重写( ...

  3. KMP算法的Next数组详解

    转载请注明来源,并包含相关链接. 网上有很多讲解KMP算法的博客,我就不浪费时间再写一份了.直接推荐一个当初我入门时看的博客吧:http://www.cnblogs.com/yjiyjige/p/32 ...

  4. hdu 2199 Can you solve this equation&quest;&lpar;高精度二分)

    http://acm.hdu.edu.cn/howproblem.php?pid=2199 Can you solve this equation? Time Limit: 2000/1000 MS ...

  5. var 与function的权重浅析

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. c&num; in deep 之LINQ简介(1)

    前两天公司进了一批书,在借阅jon skeet的c# in deep收获颇大,本书特点是介绍了不同版本的c#所增加的新特性.今天先写一下书中对linq的描述. 很多初学者在使用VS2010或2013写 ...

  7. mybatis动态数据更新 &plus; 批量动态数据插入

    动态更新 <update id="updateElevator" parameterType="com.diantijiang.saas.data.elevator ...

  8. Python爬虫入门教程 18-100 煎蛋网XXOO图片抓取

    写在前面 很高兴我这系列的文章写道第18篇了,今天写一个爬虫爱好者特别喜欢的网站煎蛋网http://jandan.net/ooxx,这个网站其实还是有点意思的,网站很多人写了N多的教程了,各种方式的都 ...

  9. linux下安装mysql-5&period;6&period;41

    1.下载安装包,下载地址:https://dev.mysql.com/downloads/mysql/5.7.html#downloads .选择完版本,然后点击下方 No thanks, just ...

  10. java多线程快速入门(九)

    多线程安全问题(卖火车票案例) package com.cppdy; class MyThread5 implements Runnable{ private Integer ticketCount= ...