读写锁

深入理解读写锁ReentrantReadWriteLock

蹲街弑〆低调 提交于 2019-12-05 19:48:39
本人免费整理了Java高级资料,涵盖了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高并发分布式等教程,一共30G,需要自己领取。 传送门: https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q 1.读写锁的介绍 1.读写锁的介绍 在并发场景中用于解决线程安全的问题,我们几乎会高频率的使用到独占式锁,通常使用java提供的关键字synchronized或者concurrents包中实现了Lock接口的。它们都是独占式获取锁,也就是在同一时刻只有一个线程能够获取锁。而在一些业务场景中,大部分只是读数据,写数据很少,如果仅仅是读数据的话并不会影响数据正确性(出现脏读),而如果在这种业务场景下,依然使用独占锁的话,很显然这将是出现性能瓶颈的地方。 针对这种读多写少的情况,java还提供了另外一个实现Lock接口的ReentrantReadWriteLock(读写锁)。读写所允许同一时刻被多个读线程访问,但是在写线程访问时,所有的读线程和其他的写线程都会被阻塞。在分析WirteLock和ReadLock的互斥性时可以按照WriteLock与WriteLock之间,WriteLock与ReadLock之间以及ReadLock与ReadLock之间进行分析

读写锁的实现

▼魔方 西西 提交于 2019-12-05 09:19:07
reference: 原子操作、内存屏障、锁 : https://www.jianshu.com/p/1d90fe6627ad 哪些操作本身是原子的? 单核处理器下中断发生在指令之间,因此单指令操作都是原子的 多核处理器下进行零次或一次对齐内存访问的汇编指令是原子的 c++版读写锁 https://blog.csdn.net/zxc024000/article/details/88814461 volatile 谈谈C/C++中的volatile: https://zhuanlan.zhihu.com/p/33074506 内存模型: https://cloud.tencent.com/developer/article/1479199 易变性。所谓的易变性,在汇编层面反映出来,就是两条语句,下一条语句不会直接使用上一条语句对应的volatile变量的寄存器内容,而是重新从内存中读取。 不可优化性。volatile告诉编译器,不要对变量进行各种激进的优化,甚至将变量直接消除,保证程序员写在代码中的指令,一定会被执行。 顺序性。能够保证Volatile变量间的顺序性,编译器不会进行乱序优化。(但CPU依然可能会乱序,x86和amd只开启了 store-load ooo ) volatile object - an object whose type is volatile

读写锁(ReadWriteLock)

让人想犯罪 __ 提交于 2019-12-05 06:38:33
读写锁(ReadWriteLock)   为了提高性能,Java提供了读写锁, 读写锁分为读锁和写锁 。多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥,这是由JVM控制的。如果没有写锁的情况下,读是无阻塞的,在一定程度上提高了程序的执行效率。 读锁   如果你的代码只读数据,可以很多人同时读,但不能同时写,那就上读锁。 写锁   如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁。总之,读的时候上读锁,写的时候上写锁。 Java中读写锁有个接口,java.util.concurrent.locks.ReadWriteLock,也有具体的实现ReentrantReadWriteLock。 代码示例: 1 public class TestReadWriteLock { 2 public static void main(String[] args) { 3 ReadWriteLockDemo rw = new ReadWriteLockDemo(); 4 new Thread(new Runnable() { 5 public void run() { 6 rw.set((int)(Math.random() * 101)); 7 } 8 }, "Write:").start(); 9 for (int i = 0; i < 100; i++) { 10 new

go sync包的读写锁RWMutex的使用

孤街浪徒 提交于 2019-12-04 23:59:00
sync包的读写锁RWMutex的使用(sync.RWMutex) 我们使用“读写”锁的场景主要是在多线程的安全操作下,并且读的情况多于写的情况,也就是说既满足多线程操作的安全性,也要确保性能不能太差,这时候,我们可以考虑使用读写锁。当然你也可以简单暴力直接使用互斥锁(Mutex)。 RWMutex的使用主要事项 1、读锁的时候无需等待读锁的结束 2、读锁的时候要等待写锁的结束 3、写锁的时候要等待读锁的结束 4、写锁的时候要等待写锁的结束 RWMutex的四种操作方法 RLock() //读锁定 RUnlock() //读解锁 Lock() //写锁定 Unlock() //写解锁 废话少说直接上代码: package main import ( "sync" "time" ) var m *sync.RWMutex func main() { m = new (sync.RWMutex) go write (1 ) go read (21 ) go write (3 ) go read (22 ) go write (4 ) go read (23 ) go write (5 ) go read (24 ) go write (6 ) go read (25 ) go write (7 ) time.Sleep (20 * time.Second) } func read(i

对BOOST 中同步互斥的一些理解

只谈情不闲聊 提交于 2019-12-03 05:56:02
对BOOST 中同步互斥的一些理解 首先,BOOST中有4种有关互斥量得概念。 1.LOCKABLE :仅支持排它型所有权 2.TIMEDLOCKABLE:支持带超时的排它型所有权 3.SHAREDLOCKABLE: 支持带超时的排他型所有权和共享型所有权(读写锁) 4.UPGRADELOCKABLE: 支持带超时的排他型所有权和共享型所有权,以及共享型所有权升级为排他型所有权(升级过程阻塞)(也支持降级) 可以看到2强化自1,3强化自2.4强化自3,支持某一概念则一定支持其强化自的概念。 boost::mutex 实现了LOCKABLE概念 (boost::recursive_mutex 是其递归锁的版本) boost::timed_mutex 实现了TIMEDLOCKABLE概念 (boost::recursive_timed_mutex 是其递归锁的版本) boost::shared_mutex实现了SHAREDLOCKABLE概念 boost::shared_mutex同样实现了UPGRADELOCKABLE概念 出于提供RAII操作风格和安全等其他一些原因BOOST不希望用户直接调用各种MUTEX类型中的相关接口,而是通过它提供的一些LOCK_TYPE来帮助我们调用。 主要的LOCK_TYPE包括: boost::unique_lock<LOCKABLE>

读写锁(ReentrantReadWriteLock)

匿名 (未验证) 提交于 2019-12-02 23:54:01
重点:   1、读锁共享   2、写锁互斥   3、读写锁互斥 锁降级 :将写锁降级为读锁。(先获取写锁,再获取读锁,再释放写锁,最后释放读锁) 造成锁降级的原因:出于性能考虑,一般情况下,都将锁定的动作,精确到具体的语句块,在两个锁的语句块之间,有可能线程的交替执行,造成线程安全问题。 解决的方法:   1、将锁的范围扩大。   2、使用锁降级。 为什么需要锁降级:  伪代码: w.lock();//写锁 writeSomeDate();//修改某些数据 w.unlock();//释放写锁 r.lock();//读锁 readSomeDate();//获取某个数据 r.unlock();//释放读锁 此时,获取数据的时候,就有线程安全问题。 修改后的代码为: w.lock();//写锁 writeSomeDate();//修改某些数据 r.lock();//读锁 w.unlock();//释放写锁 readSomeDate();//获取某个数据 r.unlock();//释放读锁 将读锁的锁定动作,放入到写锁的释放之前,就可以将锁降级为读锁。    来源: https://www.cnblogs.com/chen--biao/p/11366952.html

Linux线程间同步的几种方式

匿名 (未验证) 提交于 2019-12-02 21:56:30
信号量强调的是线程(或进程)间的同步:“信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在sem_wait的时候,就阻塞在那里)。当信号量为单值信号量时,也可以完成一个资源的互斥访问。信号量测重于访问者对资源的有序访问,在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。 可以用于不同进程间或多线程间的互斥与同步 创建打开有名信号量 sem_t *sem_open(const char *name, int oflag); sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value); //成功返回信号量指针;失败返回SEM_FAILED,设置errno name是文件路径名,但不能写成/tmp/a.sem这样的形式,因为在linux下,sem都是在/dev/shm目录下,可写成"/mysem"或"mysem",创建出来的文件都是"/dev/shm/sem.mysem",mode设置为0666,value设置为信号量的初始值.所需信号灯等已存在条件下指定O_CREAT|O_EXCL却是个错误。 关闭信号量,进程终止时,会调用它 int sem_close(sem

ReadWriteLock: 读写锁

跟風遠走 提交于 2019-12-02 21:36:25
ReadWriteLock: 读写锁 ReadWriteLock: JDK1.5提供的读写分离锁,采用读写锁分离可以有效帮助减少锁竞争。 特点: 1).使用读写锁。当线程只进行读操作时,可以允许多个线程同时读 2).写写操作,读写操作间依然需要相互等待和持有锁。 一).使用读写锁与使用重入锁进行读读写操作 开启200个线程,测试读写锁和重入锁的读效率。 使用重入锁进行读写操作: ReentrantLock_Rw import java.util.concurrent.locks.ReentrantLock; /** * 使用重入锁进行读写操作 * 线程的读写使用同一把锁。 */ public class ReentrantLock_RW { private static ReentrantLock lock = new ReentrantLock(); private static int value ; //读操作 public Object handleRead() throws InterruptedException { try { //获取锁 lock.lock(); //模拟读操作,读操作耗时越多,读写锁的优势越明显 Thread.sleep(1); return value; }finally { lock.unlock(); } } /** * 写操作 */

Linux中的各种锁及其基本原理

风流意气都作罢 提交于 2019-12-02 04:56:37
Linux中的各种锁及其基本原理 1.概述 通过本文将了解到如下内容: Linux系统的并行性特征 互斥和同步机制 Linux中常用锁的基本特性 互斥锁和条件变量 2.Linux的并行性特征 Linux作为典型的多用户、多任务、抢占式内核调度的操作系统,为了提高并行处理能力,无论在内核层面还是在用户层面都需要特殊的机制来确保任务的正确性和系统的稳定运行,就如同一个国家需要各种法律条款来约束每个公民的行为,才能有条不紊地运转。 在内核层面涉及到各种软硬件中断、进线程睡眠、抢占式内核调度、多处理器SMP架构等,因此内核在完成自己工作的时候一直在处理这些资源抢占的冲突问题。 在用户层面的进程,虽然Linux作为虚地址模式操作系统,为每个进程开辟了独立的虚拟地址空间,伪独占式拥有资源,但是仍然存在很多场景不得不产生多个进程共享资源的问题,来完成进程间的通信,但是在Go语言中进程间的通信使用消息来完成,处理地更优雅一些。 在线程层面,线程作为进程的一部分,进程内的多个线程只拥有自己的独立堆栈等少量结构,大部分的资源还是过线程共享,因此多线程的资源占用冲突比进程更加明显,所以多线程编程的线程安全问题是个重难点。综上可知,无论在kernel还是user space都必须有一些机制来确保对于资源共享问题的解决,然后这个机制就是接下来要说的:同步和互斥。 3.同步和互斥机制 基本概念

读写锁注解解决修改数据库和删除缓存的短暂时间内的数据不一致问题

时光总嘲笑我的痴心妄想 提交于 2019-11-29 22:23:06
先定义一个枚举。 package com.study.security.common.annotation; /** * @Description: 读、写锁 类型 * @Auther: BacHe * @Date: 2019/9/17 09:39 */ public enum ReadWriteType { //读锁 READ_TYPE, //写锁 WRITE_TYPE } 自定义一个注解 package com.study.security.common.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @Description: 读、写锁 注解 * @Auther: BacHe * @Date: 2019/9/17 09:41 */ //注解生命周期:运行时有有效 @Retention(RetentionPolicy.RUNTIME) //注解应用范围:修饰方法 @Target({ElementType.METHOD}) public @interface