前言

Java SDK并发包通过LockCondition两个接口来实现管程,其中Lock用于解决互斥问题,Condition用于解决同步问题。我们需要知道,Java语言本身使用synchronized实现了管程的,那么为什么还在SDK中提供另外一种实现呢?欲知为何请看下文。

下面将先阐述再造管程的理由,然后详细介绍Lock和Condition,最后再看实现同步机制时是选择synchronized还是SDK中的管程。

再造管程的理由

Java本就从语言层面实现了管程,然而后面又在SDK中再次现实,这只能说明语言层面的实现的管程有所不足。要说谈synchronized的不足,我们就要要回顾一下破坏死锁的不可抢占问题

破坏不可抢占条件,需要线程在获取不到锁的情况下主动释放它拥有的资源。当我们使用synchronized的时候,线程是没有办法主动释放它占有的资源的。因为,synchronized在申请不到资源时,会使线程直接进入阻塞状态,而线程进入了阻塞状态就不能主动释放占有的资源。

所以,有没有一种办法可以使得线程处于阻塞状态时也能够响应中断主动释放资源或者获取不到资源的时候不阻塞呢?答案是有的,使用SDK中的管程。

SDK中管程的实现java.util.concurrent中的Lock接口,提供了如下三种设计思想都可以解决死锁的不可抢占条件:

  1. 能够响应中断

    线程处于阻塞状态时可以接收中断信号。我们便可以给阻塞的线程发送中断信号,唤醒线程,线程便有机会释放它曾经拥有的锁。这样便可破坏不可抢占条件。

  2. 支持超时

    如果线程在一段时间之内没有获取到锁,不是进入阻塞状态,而是返回一个错误,那这个线程也有机会释放曾经持有的锁。这样也能破坏不可抢占条件。

  3. 非阻塞地获取锁

    如果尝试获取锁失败,并不进入阻塞状态,而是直接返回,那这个线程也有机会释放曾经持有的锁。这样也可以破坏不可抢占条件。

这三种方案就可全面弥补synchronized的问题。也就是再造管程的原因。这三种思想体现在Lock接口的API上,便是如下三个方法:

// 支持中断的 API
void lockInterruptibly() throws InterruptedException; // 支持超时的 API
boolean tryLock(long time, TimeUnit unit) throws InterruptedException; // 支持非阻塞获取锁的 API
boolean tryLock();

下面我们便继续介绍Lock。

Lock和ReentrantLock

Lock接口中定义了一组抽象的加锁操作:

public interface Lock{
void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition(); // 关联Condition对象使用
}

与synchronized内置加锁不同,Lock提供的是无条件的、可轮询的、定时的以及可中断的锁获取操作,所有加锁和解锁都是显式的。在Lock的实现中必须要提供与内置锁相同的内存可见性语义,但是加锁语义、调度算法、顺序保证以及性能等方面可以不同。

ReentrantLock实现了Lock接口,并提供了与synchronized相同的互斥性和内存可见性。在获取ReentrantLock时,有着进入同步代码块相同的内存语义,在释放ReentrantLock时,同样有着与退出同步代码块相同的内存语义。见名知义,ReentrantLock还提供了同synchronized一样的可重入加锁的语义。

【Java并发工具类】Lock和Condition的更多相关文章

  1. 基于AQS实现的Java并发工具类

    本文主要介绍一下基于AQS实现的Java并发工具类的作用,然后简单谈一下该工具类的实现原理.其实都是AQS的相关知识,只不过在AQS上包装了一下而已.本文也是基于您在有AQS的相关知识基础上,进行讲解 ...

  2. Java并发工具类 - CountDownLatch

    Java并发工具类 - CountDownLatch 1.简介 CountDownLatch是Java1.5之后引入的Java并发工具类,放在java.util.concurrent包下面 http: ...

  3. 25.大白话说java并发工具类-CountDownLatch,CyclicBarrier,Semaphore,Exchanger

    1. 倒计时器CountDownLatch 在多线程协作完成业务功能时,有时候需要等待其他多个线程完成任务之后,主线程才能继续往下执行业务功能,在这种的业务场景下,通常可以使用Thread类的join ...

  4. Java并发工具类CountDownLatch源码中的例子

    Java并发工具类CountDownLatch源码中的例子 实例一 原文描述 /** * <p><b>Sample usage:</b> Here is a pai ...

  5. 【Java并发工具类】Semaphore

    前言 1965年,荷兰计算机科学家Dijkstra提出的信号量机制成为一种高效的进程同步机制.这之后的15年,信号量一直都是并发编程领域的终结者.1980年,管程被提出,成为继信号量之后的在并发编程领 ...

  6. java 并发工具类CountDownLatch & CyclicBarrier

    一起在java1.5被引入的并发工具类还有CountDownLatch.CyclicBarrier.Semaphore.ConcurrentHashMap和BlockingQueue,它们都存在于ja ...

  7. JAVA并发工具类---------------(CountDownLatch和CyclicBarrier)

    CountDownLatch是什么 CountDownLatch,英文翻译为倒计时锁存器,是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 闭锁可以延迟线程的进 ...

  8. 【Java并发工具类】Java并发容器

    前言 Java并发包有很大一部分都是关于并发容器的.Java在5.0版本之前线程安全的容器称之为同步容器.同步容器实现线程安全的方式:是将每个公有方法都使用synchronized修饰,保证每次只有一 ...

  9. 【Java并发工具类】ReadWriteLock

    前言 前面介绍过ReentrantLock,它实现的是一种标准的互斥锁:每次最多只有一个线程能持有ReentrantLock.这是一种强硬的加锁规则,在某些场景下会限制并发性导致不必要的抑制性能.互斥 ...

随机推荐

  1. 根据设备id自动打开本设备的串口

    对于串口设备经常遇到重新拔插串口设备时候,程序又需要重新选择串口打开.对此很少麻烦的要死. 现在我们可以根据该设备的id去遍历串口设备,一旦符合就打开此串口即可. public void init() ...

  2. 从零开始のcocos2dx生活(二)Node

    节点 Node 文章目录 节点 Node 前言 变量初始化 创建一个节点对象 获取节点依赖的计数器 获取节点的描述(获取节点的Tag) 节点的局部层顺序值(LocalZOrder) 设置节点的Loca ...

  3. 洛谷$P3749$ [六省联考2017] 寿司餐厅 网络流

    正解:网络流 解题报告: 传送门$QwQ$ 这道题好烦昂,,,就给了好多变量,,,但仔细读一遍题还是能$get$的所以我就不再提取一遍题目大意辣$QwQ$? 显然考虑建两排点,一排收益一排支出然后最小 ...

  4. iOS颜色转换成图片的方法

    // 颜色转换为背景图片 - (UIImage *)imageWithColor:(UIColor *)color { CGRect rect = CGRectMake(0.0f, 0.0f, 1.0 ...

  5. Python学到什么程度可以面试工作(解答一)

    本文整理了 26 个 Python 有用的技巧,将按照首字母从 A~Z 的顺序分享其中一些内容. all 或 any 人们经常开玩笑说 Python 是“可执行的伪代码”,但是当你可以这样编写代码时, ...

  6. Ncverilog 仿真quartus generate IP的要点

    Ncverilog 仿真quartus generate IP的要点 最近利用quartus II 生成plll 的IP,利用nclaunch 仿真的时候老是报错, 提示unresolved in w ...

  7. springmvc接收json数据的常见方式

    经常使用Ajax异步请求来进行数据传输,传的数据是json数据,json数据又有对象,数组.所有总结下springmvc获取前端传来的json数据方式:1.以RequestParam接收前端传来的是j ...

  8. 解决:'chromedriver' executable needs to be in PATH的问题

    0.前言 今天写一个B站登录的模拟器时,用到了Chrome浏览器,但是会报了一个异常"'chromedriver' executable needs to be in PATH", ...

  9. Office系列(2)---提取Office文件(Word、PPT)中的所有图片

    回顾一下上文结尾的问题:如何给文档设置一个合适的封面图?其中一个解决方案就是,获取Office文件内部的图片作为封面.这里就详细介绍下获取图片的几种方式,以及他们各自的优缺点. PS:因为之前用VST ...

  10. Java 中的等待唤醒机制透彻讲解

    线程的状态 首先了解一下什么是线程的状态,线程状态就是当线程被创建(new),并且启动(start)后,它不是一启动就进入了执行状态(run),也不是一直都处于执行状态. 这里说一下Java 的Thr ...