cocurrent包 锁 Lock
20. 锁 Lock
java.util.concurrent.locks.Lock 是一个类似于 synchronized 块的线程同步机制。但是 Lock 比 synchronized 块更加灵活、精细。
顺便说一下,在我的《Java 并发指南》中我对如何实现你自己的锁进行了描述。
Java Lock 例子
既然 Lock 是一个接口,在你的程序里需要使用它的实现类之一来使用它。以下是一个简单示例:
- Lock lock = new ReentrantLock();
- lock.lock();
- //critical section
- lock.unlock();
首先创建了一个 Lock 对象。之后调用了它的 lock() 方法。这时候这个 lock 实例就被锁住啦。任何其他再过来调用 lock() 方法的线程将会被阻塞住,直到锁定 lock 实例的线程调用了 unlock() 方法。最后 unlock() 被调用了,lock 对象解锁了,其他线程可以对它进行锁定了。
Java Lock 实现
java.util.concurrent.locks 包提供了以下对 Lock 接口的实现类:
- ReentrantLock
Lock 和 synchronized 代码块的主要不同点
一个 Lock 对象和一个 synchronized 代码块之间的主要不同点是:
- synchronized 代码块不能够保证进入访问等待的线程的先后顺序。
- 你不能够传递任何参数给一个 synchronized 代码块的入口。因此,对于 synchronized 代码块的访问等待设置超时时间是不可能的事情。
- synchronized 块必须被完整地包含在单个方法里。而一个 Lock 对象可以把它的 lock() 和 unlock() 方法的调用放在不同的方法里。
Lock 的方法
Lock 接口具有以下主要方法:
- lock()
- lockInterruptibly()
- tryLock()
- tryLock(long timeout, TimeUnit timeUnit)
- unlock()
lock() 将 Lock 实例锁定。如果该 Lock 实例已被锁定,调用 lock() 方法的线程将会阻塞,直到 Lock 实例解锁。
lockInterruptibly() 方法将会被调用线程锁定,除非该线程被打断。此外,如果一个线程在通过这个方法来锁定 Lock 对象时进入阻塞等待,而它被打断了的话,该线程将会退出这个方法调用。
tryLock() 方法试图立即锁定 Lock 实例。如果锁定成功,它将返回 true,如果 Lock 实例已被锁定该方法返回 false。这一方法永不阻塞。
tryLock(long timeout, TimeUnit timeUnit) 的工作类似于 tryLock() 方法,除了它在放弃锁定 Lock 之前等待一个给定的超时时间之外。
unlock() 方法对 Lock 实例解锁。一个 Lock 实现将只允许锁定了该对象的线程来调用此方法。其他(没有锁定该 Lock 对象的线程)线程对 unlock() 方法的调用将会抛一个未检查异常(RuntimeException)。
21. 读写锁 ReadWriteLock
java.util.concurrent.locks.ReadWriteLock 读写锁是一种先进的线程锁机制。它能够允许多个线程在同一时间对某特定资源进行读取,但同一时间内只能有一个线程对其进行写入。
读写锁的理念在于多个线程能够对一个共享资源进行读取,而不会导致并发问题。并发问题的发生场景在于对一个共享资源的读和写操作的同时进行,或者多个写操作并发进行。
本节只讨论 Java 内置 ReadWriteLock。如果你想了解 ReadWriteLock 背后的实现原理,请参考我的《Java 并发指南》主题中的《读写锁》小节。
ReadWriteLock 锁规则
一个线程在对受保护资源在读或者写之前对 ReadWriteLock 锁定的规则如下:
- 读锁:如果没有任何写操作线程锁定 ReadWriteLock,并且没有任何写操作线程要求一个写锁(但还没有获得该锁)。因此,可以有多个读操作线程对该锁进行锁定。
- 写锁:如果没有任何读操作或者写操作。因此,在写操作的时候,只能有一个线程对该锁进行锁定。
ReadWriteLock 实现
ReadWriteLock 是个接口,如果你想用它的话就得去使用它的实现类之一。java.util.concurrent.locks 包提供了 ReadWriteLock 接口的以下实现类:
- ReentrantReadWriteLock
ReadWriteLock 代码示例
以下是 ReadWriteLock 的创建以及如何使用它进行读、写锁定的简单示例代码:
- ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
- readWriteLock.readLock().lock();
- // multiple readers can enter this section
- // if not locked for writing, and not writers waiting
- // to lock for writing.
- readWriteLock.readLock().unlock();
- readWriteLock.writeLock().lock();
- // only one writer can enter this section,
- // and only if no threads are currently reading.
- readWriteLock.writeLock().unlock();
注意如何使用 ReadWriteLock 对两种锁实例的持有。一个对读访问进行保护,一个队写访问进行保护。
cocurrent包 锁 Lock的更多相关文章
- java 锁 Lock接口详解
一:java.util.concurrent.locks包下常用的类与接口(lock是jdk 1.5后新增的) (1)Lock和ReadWriteLock是两大锁的根接口,Lock代表实现类是Reen ...
- Java同步锁——lock与synchronized 的区别【转】
在网上看来很多关于同步锁的博文,记录下来方便以后阅读 一.Lock和synchronized有以下几点不同: 1)Lock是一个接口,而synchronized是Java中的关键字,synchroni ...
- 并发、并行、同步、异步、全局解释锁GIL、同步锁Lock、死锁、递归锁、同步对象/条件、信号量、队列、生产者消费者、多进程模块、进程的调用、Process类、
并发:是指系统具有处理多个任务/动作的能力. 并行:是指系统具有同时处理多个任务/动作的能力. 并行是并发的子集. 同步:当进程执行到一个IO(等待外部数据)的时候. 异步:当进程执行到一个IO不等到 ...
- Java并发处理锁 Lock
在上一篇文章中我们讲到了如何使用关键字synchronized来实现同步访问.本文我们继续来探讨这个问题,从Java 5之后,在 java.util.concurrent.locks 包下提供了另外一 ...
- python笔记9 线程进程 threading多线程模块 GIL锁 multiprocessing多进程模块 同步锁Lock 队列queue IO模型
线程与进程 进程 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及如何完成:数据集则是程序在执行过程中所需要 ...
- Java核心知识点学习----线程中如何创建锁和使用锁 Lock,设计一个缓存系统
理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的. 1.如何创建锁? Lock lock = new ReentrantLock(); ...
- 8. 同步锁Lock
package com.gf.demo07; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Ree ...
- 进程锁Lock
例1: 10个人去买票,先去查询余票,有票就去购买.代码如下: # ticket.py {"ticket": 1} # 只有一张票 import json import time ...
- “全栈2019”Java多线程第三十二章:显式锁Lock等待唤醒机制详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
随机推荐
- 爬虫:Scrapy15 - 调试(Debugging)Spiders
考虑下面的 spider: import scrapy from myproject.items import MyItem class MySpider(scrapy.Spider): name = ...
- [译]如何将docker日志重定向到单个文件里
原文来源: how-to-redirect-docker-logs-to-a-single-file 问题: 我想把某一个docker的log全部导出到一个文件里进行分析,我该怎么做? 其实不用那样操 ...
- hdu 2492 树状数组 Ping pong
欢迎参加——BestCoder周年纪念赛(高质量题目+多重奖励) Ping pong Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 3 ...
- FileZilla修改文件大小格式
之前使用FileZilla觉得很奇怪,文件大小显示为字节格式,很不习惯. 最近发现是在这里修改. 菜单“编辑”下选择设置,选择选项“文件大小格式”,在右边选择为:“使用SI式二进制前缀.(如 1 KB ...
- ci重写 配置文件
server { listen 80; #listen [::]:80; server_name wangyongshun.xyz www.wangyongshun.xyz; index index. ...
- hdu 1195 Open the Lock (BFS)
Open the Lock Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tot ...
- 关于ECDSA/ECC(密钥加密传输)和ECDSA/ECDH(密钥磋商)
关于ECDSA/ECC(密钥加密传输)和ECDSA/ECDH(密钥磋商) 来源: https://blog.csdn.net/xueyepiaoling/article/details/6243337 ...
- Bsd内核选项总结
Bsd内核选项总结 一: 下面这个选项在每个内核中都要有: machine i386 它指明了机器的硬件体系结构.它必须是i386, pc98, sparc64, alpha, ia64, amd64 ...
- ie6中margin失效问题
在div的外面添加父级div并设置 padding-bottom: 10px;! <!DOCTYPE html><html><head lang="en&quo ...
- 使用 redux 监听插件的使用
首先需要在chrome浏览器当中下载redux插件 接着在你的项目当中加上**window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX ...