并发编程实战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列表去重的4种核心方法与实战指南详解

《Python列表去重的4种核心方法与实战指南详解》在Python开发中,处理列表数据时经常需要去除重复元素,本文将详细介绍4种最实用的列表去重方法,有需要的小伙伴可以根据自己的需要进行选择... 目录方法1:集合(set)去重法(最快速)方法2:顺序遍历法(保持顺序)方法3:副本删除法(原地修改)方法4:

在Spring Boot中浅尝内存泄漏的实战记录

《在SpringBoot中浅尝内存泄漏的实战记录》本文给大家分享在SpringBoot中浅尝内存泄漏的实战记录,结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录使用静态集合持有对象引用,阻止GC回收关键点:可执行代码:验证:1,运行程序(启动时添加JVM参数限制堆大小):2,访问 htt

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

Pandas使用SQLite3实战

《Pandas使用SQLite3实战》本文主要介绍了Pandas使用SQLite3实战,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录1 环境准备2 从 SQLite3VlfrWQzgt 读取数据到 DataFrame基础用法:读

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步