并发编程实战13-同步中的四种锁synchronized、ReentrantLock、ReentrantReadWriteLock、StampedLock

本文主要是介绍并发编程实战13-同步中的四种锁synchronized、ReentrantLock、ReentrantReadWriteLock、StampedLock,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  1. synchronized同步锁
    • synchronized属于悲观锁,直接对区域或者对象加锁,性能稳定,可以使用大部分场景。
  2. ReentrantLock可重入锁(Lock接口)
    • 相对于synchronized更加灵活,可以控制加锁和放锁的位置
    • 可以使用Condition来操作线程,进行线程之间的通信
    • 核心类AbstractQueuedSynchronizer,通过构造一个基于阻塞的CLH队列容纳所有的阻塞线程,而对该队列的操作均通过Lock-Free(CAS)操作,但对已经获得锁的线程而言,ReentrantLock实现了偏向锁的功能。
  3. ReentrantReadWriteLock可重入读写锁(ReadWriteLock接口)
    • 相对于ReentrantLock,对于大量的读操作,读和读之间不会加锁,只有存在写时才会加锁,但是这个锁是悲观锁
    • ReentrantReadWriteLock实现了读写锁的功能
    • ReentrantReadWriteLock是ReadWriteLock接口的实现类。ReadWriteLock接口的核心方法是readLock(),writeLock()。实现了并发读、互斥写。但读锁会阻塞写锁,是悲观锁的策略。
  4. StampedLock戳锁
    • ReentrantReadWriteLock虽然解决了大量读取的效率问题,但是,由于实现的是悲观锁,当读取很多时,读取和读取之间又没有锁,写操作将无法竞争到锁,就会导致写线程饥饿。所以就需要对读取进行乐观锁处理。
    • StampedLock加入了乐观读锁,不会排斥写入
    • 当并发量大且读远大于写的情况下最快的的是StampedLock锁

StampedLock控制锁有三种模式(排它写,悲观读,乐观读),一个StampedLock状态是由版本和模式两个部分组成,锁获取方法返回一个数字作为票据stamp,它用相应的锁状态表示并控制访问。

StampedLock主要使用的是乐观读取,通过一个stamp变量来检测是否有读写冲突,每次乐观读取时会加入stamp校验。当存在写入操作时,写操作会改变stamp的状态,就会导致乐观读取失败,乐观读锁就会升级为悲观读锁

package com.sound.daytd5;import java.util.concurrent.locks.StampedLock;/*** @author: ZouTai* @date: 2018/4/17* @description:*/
public class StampedLockDemo {private int balance;private final StampedLock stampedLock = new StampedLock();/*** 1、悲观写* writeLock():典型的cas操作,如果STATE等于s,设置写锁位为1(s+WBIT)。* acquireWrite跟acquireRead逻辑类似,先自旋尝试、加入等待队列、直至最终Unsafe.park()挂起线程。*/public void write(int i) {long stamp = stampedLock.writeLock();balance += i;stampedLock.unlockWrite(stamp);}/*** 2、悲观读* 乐观锁失败后锁升级为readLock():尝试state+1,用于统计读线程的数量,* 如果失败,进入acquireRead()进行自旋,通过CAS获取锁。* 如果自旋失败,入CLH队列,然后再自旋,* 如果成功获得读锁,激活cowait队列中的读线程Unsafe.unpark(),* 最终依然失败,Unsafe().park()挂起当前线程。*/public void read() {long stamp = stampedLock.readLock();int value = balance;stampedLock.unlockRead(stamp);}/**重点:!!!* 3、乐观读:当读取远远大于写入时,使用乐观锁* tryOptimisticRead():如果当前没有写锁占用,返回state(后7位清0,即清0读线程数),如果有写锁,返回0,即失败。*/public void optimisticRead() {long stamp = stampedLock.tryOptimisticRead();int value = balance;// 校验这个戳是否有效validate():比较当前stamp和发生乐观锁得到的stamp比较,不一致则失败。if(!stampedLock.validate(stamp)) {long readStamp = stampedLock.readLock();value = balance;stamp = readStamp;}stampedLock.unlockRead(stamp);}/**重点:!* 4、判断条件之后,再写* 存在读取和写入两个操作*/public void conditionReadWrite(int state){// 首先读取long stamp = stampedLock.readLock();while (balance > 100){long writeStamp = stampedLock.tryConvertToWriteLock(stamp);// 步骤:aif(writeStamp!=0) {balance += state;stamp = writeStamp;break;} else {// 转换失败stampedLock.unlockRead(stamp);//显式直接进行写锁 然后再通过循环再试,回到 步骤:astamp = stampedLock.writeLock();}}}}

同步中四种锁的性能比较
同步中的四种锁synchronized、ReentrantLock、ReentrantReadWriteLock、StampedLock
同步锁参考英文文档

这篇关于并发编程实战13-同步中的四种锁synchronized、ReentrantLock、ReentrantReadWriteLock、StampedLock的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/640150

相关文章

Python并行处理实战之如何使用ProcessPoolExecutor加速计算

《Python并行处理实战之如何使用ProcessPoolExecutor加速计算》Python提供了多种并行处理的方式,其中concurrent.futures模块的ProcessPoolExecu... 目录简介完整代码示例代码解释1. 导入必要的模块2. 定义处理函数3. 主函数4. 生成数字列表5.

canal实现mysql数据同步的详细过程

《canal实现mysql数据同步的详细过程》:本文主要介绍canal实现mysql数据同步的详细过程,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的... 目录1、canal下载2、mysql同步用户创建和授权3、canal admin安装和启动4、canal

Linux实现线程同步的多种方式汇总

《Linux实现线程同步的多种方式汇总》本文详细介绍了Linux下线程同步的多种方法,包括互斥锁、自旋锁、信号量以及它们的使用示例,通过这些同步机制,可以解决线程安全问题,防止资源竞争导致的错误,示例... 目录什么是线程同步?一、互斥锁(单人洗手间规则)适用场景:特点:二、条件变量(咖啡厅取餐系统)工作流

Mysql的主从同步/复制的原理分析

《Mysql的主从同步/复制的原理分析》:本文主要介绍Mysql的主从同步/复制的原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录为什么要主从同步?mysql主从同步架构有哪些?Mysql主从复制的原理/整体流程级联复制架构为什么好?Mysql主从复制注意

Java Spring 中的监听器Listener详解与实战教程

《JavaSpring中的监听器Listener详解与实战教程》Spring提供了多种监听器机制,可以用于监听应用生命周期、会话生命周期和请求处理过程中的事件,:本文主要介绍JavaSprin... 目录一、监听器的作用1.1 应用生命周期管理1.2 会话管理1.3 请求处理监控二、创建监听器2.1 Ser

Apache 高级配置实战之从连接保持到日志分析的完整指南

《Apache高级配置实战之从连接保持到日志分析的完整指南》本文带你从连接保持优化开始,一路走到访问控制和日志管理,最后用AWStats来分析网站数据,对Apache配置日志分析相关知识感兴趣的朋友... 目录Apache 高级配置实战:从连接保持到日志分析的完整指南前言 一、Apache 连接保持 - 性

MQTT SpringBoot整合实战教程

《MQTTSpringBoot整合实战教程》:本文主要介绍MQTTSpringBoot整合实战教程,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录MQTT-SpringBoot创建简单 SpringBoot 项目导入必须依赖增加MQTT相关配置编写

Mac备忘录怎么导出/备份和云同步? Mac备忘录使用技巧

《Mac备忘录怎么导出/备份和云同步?Mac备忘录使用技巧》备忘录作为iOS里简单而又不可或缺的一个系统应用,上手容易,可以满足我们日常生活中各种记录的需求,今天我们就来看看Mac备忘录的导出、... 「备忘录」是 MAC 上的一款常用应用,它可以帮助我们捕捉灵感、记录待办事项或保存重要信息。为了便于在不同

python多线程并发测试过程

《python多线程并发测试过程》:本文主要介绍python多线程并发测试过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、并发与并行?二、同步与异步的概念?三、线程与进程的区别?需求1:多线程执行不同任务需求2:多线程执行相同任务总结一、并发与并行?1、

查看MySql主从同步的偏移量方式

《查看MySql主从同步的偏移量方式》:本文主要介绍查看MySql主从同步的偏移量方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 1.mysql的主从同步方案mysqlphp为了在实现读写分离,主库写,从库读mysql的同步方案主要是通过从库读取主库的binl