java并发编程专题(四)----浅谈(JUC)Lock锁
作者:rickiyang 发布时间:2021-11-30 00:20:23
首先我们来回忆一下上一节讲过的synchronized关键字,该关键字用于给代码段或方法加锁,使得某一时刻它修饰的方法或代码段只能被一个线程访问。那么试想,当我们遇到这样的情况:当synchronized修饰的方法或代码段因为某种原因(IO异常或是sleep方法)被阻塞了,但是锁有没有被释放,那么其他线程除了等待以外什么事都做不了。当我们遇到这种情况该怎么办呢?我们今天讲到的Lock锁将有机会为此行使他的职责。
1.为什么需要Lock
synchronized 是Java 语言层面的,是内置的关键字;Lock 则是JDK 5 的J.U.C(java/util/currrent)包中出现的一个类,在使用时,synchronized 同步的代码块可以由JVM自动释放;Lock 需要程序员在finally块中手工释放;synchronized是比较古老的实现机制,设计较早,有一些功能上的限制:
——它无法中断一个正在等候获得锁的线程
——也无法通过投票得到锁,如果不想等下去,也就没法得到锁。
——同步还要求锁的释放只能在与获得锁所在的堆栈帧相同的堆栈帧中进行
而且对多线程环境中,使用synchronized后,线程要么获得锁,执行相应的代码,要么无法获得锁处于等待状态,对于锁的处理不灵活。而Lock提供了多种基于锁的处理机制,比如:
void lock(),获取一个锁,如果锁当前被其他线程获得,当前的线程将被休眠。
boolean tryLock(),尝试获取一个锁,如果当前锁被其他线程持有,则返回false,不会使当前线程休眠。
boolean tryLock(long timeout,TimeUnit unit),如果获取了锁定立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁定,就返回true,如果等待超时,返回false。
void lockInterruptibly(),如果获取了锁定立即返回,如果没有获取锁定,当前线程处于休眠状态,直到或者锁定,或者当前线程被别的线程中断。
可见lock比synchronized提供了更细的粒度、更灵活的控制。
2.初探Lock
在jdk1.5之后,并发包中新增了Lock接口(以及相关实现类)用来实现锁功能,其实真正的实现Lock接口的类就三个,ReentrantLock和ReentrantReadWriteLock的两个内部类(ReadLock和WriteLock实现了Lock的接口),下面我们来看一下Lock的类图:
ReentrantLock:一个可重入的互斥锁,为lock接口的主要实现。
ReentrantReadWriteLock:
ReadWriteLock、ReadWriteLock 维护了一对相关的锁,一个用于只读操作,另一个用于写入操作。
Semaphore:一个计数信号量。
Condition:锁的关联条件,目的是允许线程获取锁并且查看等待的某一个条件是否满足。
CyclicBarrier:一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点。
①首先我们来看一下Lock的用法:
Lock lock = new ReentrantLock();
lock.lock();
try{
//处理任务
}catch(Exception ex){
}finally{
lock.unlock(); //释放锁
}
正常使用Lock的用法最多就是这样,ReentrantLock是Lock的实现类们也是最常使用的。如果采用Lock,必须主动去释放锁,并且在发生异常时,不会自动释放锁。因此一般来说,使用Lock必须在try{}catch{}块中进行,并在finally块释放锁,以保证锁一定被被释放,防止死锁的发生。
②我们也可以这样使用Lock:
Lock lock = new ReentrantLock();
if(lock.tryLock()) {
try{
//处理任务
}catch(Exception ex){
}finally{
lock.unlock(); //释放锁
}
}else {
//如果不能获取锁,则直接做其他事情
}
tryLock()方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取)则返回false,也就说这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待。
这一节我们简单了解一下Lock接口,由于Lock锁的内容实在是太多,包括互斥锁,公平锁,非公平锁,共享锁以及相关的条件机制,信号量机制等等,我会一点点的把他们都啃下来,下面才是我们的重头戏。
来源:https://www.cnblogs.com/rickiyang/p/11074266.html
猜你喜欢
- 说到事件机制,可能脑海中最先浮现的就是日常使用的各种 listener,listener去监听事件源,如果被监听的事件有变化就会通知list
- Java 线程池原理Executor框架的两级调度模型在HotSpot VM的模型中,Java线程被一对一映射为本地操作系统线程。JAVA线
- 1、错误的解决方案1.1、 先更新数据库,再删除缓存若数据库更新成功,删除缓存操作失败,则此后读到的都是缓存中过期的数据,造成不一致问题。1
- 一、理解slf4j(Simple Logging Facade for Java),表示为java提供的简单日志门面,更底层一点说就是接口。
- class Dirctonary { &nbs
- java "equals"和"==”异同首先简单说一下“equal”和“==”==操作对于基本数据类型比较的是
- 概述透视表是依据已有数据源来创建的交互式表格,我们可在excel中创建透视表,也可编辑已有透视表。所需工具:Free Spire.XLS f
- 一.导入方式由于jdk中没有servlet对应的jar包,所以需要咱们手动引入,有两种方式:1.可以采取向lib目录导入servlet-ap
- 概述从今天开始, 小白我将带大家开启 Jave 数据结构 & 算法的新篇章.队列队列 (Queue) 遵循先进先出的原则 (Firs
- 一、简介  Apache ShardingSphere 是一套开源的分布式数据库解决方案组成的生态圈,它
- 一.什么是CASCAS(Compare And Swap,比较并交换),通常指的是这样一种原子操作:针对一个变量,首先比较它的内存值与某个期
- 首先,需要一个电话号码,目前很多账户都是将账户名设置成手机号,然后点击按钮获取手机验证码。 其次,你需要后台给你手机短信的验证接口,各个公司
- Spring多配置文件有什么好处? 按照目的、功能去拆分配置文件,可以提高配置文件的可读性与维护性,如将配置事务管理、数据源等少改动的配置与
- 最近学习了一下seata,由于nacos现在也挺火,于是学习了seata注册到nacos,然后集成springcloud1.nacos配置(
- 工厂方法模式的定义工厂方法(Factory Method)模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂
- 1.添加引用Windows服务(.NET Framework)2.输入项目名称,选择安装位置,,选择安装框架版本;创建。3.找到MyServ
- 新建两个工程,一个客户端,一个服务端,先启动服务端再启动客户端两个工程的读写操作线程类基本上完全相同服务端:import java.io.B
- 本文实例讲述了Android桌面组件App Widget用法。分享给大家供大家参考。具体如下:Android开发应用除了程序应用,还有App
- 目录实现方法问题在出问题的设备上,使用简单的Show()、Active()方法激活窗口是不行的,只会在任务栏闪烁图标,使用如下方法可以激活实
- pom.xml与settings.xmlpom.xml与setting.xml,可以说是Maven中最重要的两个配置文件,决定了Maven的