前言

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. 洛谷$P$3301 $[SDOI2013]$方程 $exLucas$+容斥

    正解:$exLucas$+容斥 解题报告: 传送门! 在做了一定的容斥的题之后再看到这种题自然而然就应该想到容斥,,,? 没错这题确实就是容斥,和这题有点儿像 注意下的是这里的大于和小于条件处理方式不 ...

  2. Linux常用命令大全(三)

    Linux常用命令大全(三) 文件类型 普通文件(文本文件.数据文件.可执行的二进制文件) 目录文件 同上 差别:由成对的"I节点号.文件名"构成的列表 设备文件 (字符设备.块设 ...

  3. js中this指向问题(call,apply,bind)

    call.apply.bind的作用是改变函数运行时this的指向. 如果你传的 context 就 null 或者 undefined,那么 window 对象就是默认的 context(严格模式下 ...

  4. centos下MySQL登录1045问题解决

    由于需要在centos下部署整个应用,自然少不了对数据库的操作.但很多人可能会遇到一些问题,比如创建用户成功,但是却无法登录. 无法登陆一般就两个原因.第一,远程访问端口没开,第二个原因就是密码错误了 ...

  5. 1053 住房空置率 (20 分)C语言

    在不打扰居民的前提下,统计住房空置率的一种方法是根据每户用电量的连续变化规律进行判断.判断方法如下: 在观察期内,若存在超过一半的日子用电量低于某给定的阈值 e,则该住房为"可能空置&quo ...

  6. 超级火的java自学网站

    学靠的是毅力和自律,一定要坚持,否则就会前功尽弃,我自己也一直在边学边工作,当然自学要配合好的学习资料. 我是通过这个地方去学习的,它可以添加学习计划,从java基础到高级,从后台到前端,从细节到框架 ...

  7. Vue中echarts的基本用法

    前言:同大多数的前端框架一样,先读官网的使用方法.学会基本使用后,在实例中找到自己想要demo.拿过来改一改,一个echarts图表就形成,毕竟人家做就是为了方便使用. 我是在vue中下面直接使用的e ...

  8. [apue] 作为 daemon, 启动 Unix Domain Socket 侦听失败?

    前段时间写一个传递文件句柄的小 demo,有 server 端.有 client 端,之间通过 Unix Domain Socket 通讯. 在普通模式下,双方可以正常建立连接,当server端作为d ...

  9. mysql 查询中文数据

    select * from comm_user WHERE length(tags)!=CHAR_LENGTH(tags)

  10. MQ如何解决消息的顺序问题和消息的重复问题?

    一.摘要 分布式消息系统作为实现分布式系统可扩展.可伸缩性的关键组件,需要具有高吞吐量.高可用等特点.而谈到消息系统的设计,就回避不了两个问题: 1.消息的顺序问题 2.消息的重复问题 二.关键特性以 ...