首页 > 其他分享 >Lock

Lock

时间:2023-09-18 22:08:21浏览次数:26  
标签:加锁 synchronized Lock 线程 公平 lock 共享

乐观锁

常用代表:CAS

什么是乐观锁?永远处于乐观积极状态,因此乐观锁觉得并发操作期间是不会出问题的,操作数据 不加锁,只会在最后更新数据时检查数据有没有被修改,没有的话才更新(更新期间加锁,保证是原子性的)。

JavaPub手绘:乐观锁

提到 CAS,这个也是高频考点。大白话介绍一下、便于更好理解乐观锁。

CAS 是一种乐观锁实现机制(比较并替换),主要是三部分:内存值+旧的预期值+要修改的值。每次修改数据先比较内存中值与预期值是否相同,不同就自旋,相同才修改。实现依靠unsafe(里面全是native修饰的本地方法,可以直接调用操作系统) + lock cmpxchg(底层依靠硬件指令)。

当然CAS的特性也导致了它的 缺点,ABA问题、自旋导致的资源浪费、只能保障一个变量的原子性。

悲观锁

顾名思义,永远处于悲观消极状态,因此悲观锁觉得并发操作每次都可能有问题,于是每次都会加锁。

所以每次在读写数据的时候都会上锁,这样别人想读写这个数据就会阻塞住直到拿到锁 Java 中的悲观锁就是 Synchronized、AQS 框架下的锁则是先尝试 cas 乐观锁去获取锁,获取不到,才会转换为悲观锁,如 RetreenLock。

乐观锁 VS 悲观锁

乐观锁适用于读多写少的场景,因为它是不加锁的,相较于悲观锁不用加锁、释放锁,节省了开销。但是若写的多,冲突严重,可能导致线程一直 while 自旋,浪费资源,反而降低了性能。此时在这种写多读少的场景使用悲观锁就更合适。

独占锁

[独享锁、排它锁]

独占锁锁一次只能被一个线程所持有。如果线程 T 对数据 A 加上排它锁后,则其他线程不能再对 A 加任何类型的锁。获得排它锁的线程即能读数据又能修改数据。JDK 中的 synchronized 和 JUC 中 Lock 的实现类就是互斥锁。

共享锁

共享锁是指该锁可被多个线程所持有。如果线程T对数据A加上共享锁后,则其他线程只能对A再加共享锁,不能加排它锁。获得共享锁的线程只能读数据,不能修改数据。

需要注意的是,对于Java ReentrantLock 而言,其是独享锁。但是对于 Lock 的另一个实现类 ReadWriteLock,其读锁是共享锁,其写锁是独占锁。读锁的共享锁可保证并发读是非常高效的,读写,写读,写写的过程是互斥的。独占锁与共享锁也是通过 AQS 来实现的,通过实现不同的方法,来实现独享或者共享。

公平锁

常见代表:new ReentrantLock(true)、new ReentrantReadWriteLock(true)

公平锁 是指多个线程按照申请锁的顺序来获取锁,线程直接进入队列中排队,队列中的第一个线程才能获得锁。

公平锁的优点是等待锁的线程不会饿死。缺点是整体吞吐效率相对非公平锁要低,等待队列中除第一个线程以外的所有线程都会阻塞,CPU 唤醒阻塞线程的开销比非公平锁大。

非公平锁

常见代表:synchronized、new ReentrantLock(false)、new ReentrantReadWriteLock(false)

非公平锁 是多个线程加锁时直接尝试获取锁,获取不到才会到等待队列的队尾等待。但如果此时锁刚好可用,那么这个线程可以无需阻塞直接获取到锁,所以非公平锁有可能出现后申请锁的线程先获取锁的场景。

非公平锁的优点是可以减少唤起线程的开销,整体的吞吐效率高,因为线程有几率不阻塞直接获得锁,CPU 不必唤醒所有线程。缺点是处于等待队列中的线程可能会饿死,或者等很久才会获得锁。

synchronized 和 lock 对比更有助于理解公平锁和非公平锁。

  • synchronized 自动释放锁,lock 手动释放(容易死锁) lock.unlock();synchronized 阻塞后,其他线程一直等待,lock有超时时间。
  • lock 等待锁过程中可以用 interrupt 来中断等待,而 synchronized 只能等待锁的释放,不能响应中断。
  • synchronized 使用 Object 对象本身的 wait 、 notify、notifyAll 调度机制,而 Lock 可以使用 Condition 进行线程之间的调度。

分段锁

标签:加锁,synchronized,Lock,线程,公平,lock,共享
From: https://blog.51cto.com/wangshiyu/7515638

相关文章

  • 科技云报道:分布式存储红海中,看天翼云HBlock如何突围?
    科技云报道原创。过去十年,随着技术的颠覆性创新和新应用场景的大量涌现,企业IT架构出现了稳态和敏态的混合化趋势。在持续产生海量数据的同时,这些新应用、新场景在基础设施层也普遍基于敏态的分布式架构构建,从而对存储技术提出了新的要求。正因如此,分布式存储凭借高安全性、可靠性、......
  • python多线程中锁的概念 threading.Lock
    https://blog.csdn.net/qq_21439971/article/details/79356248 python的锁可以独立提取出来12345678mutex  =  threading.Lock()#锁的使用#创建锁mutex  =  threading.Lock()#锁定mutex.acquire([timeout])#释放mutex.release()......
  • linux --- 自旋锁(spinlock_t)
    定义自旋锁与互斥锁有点类似,只是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,”自旋”一词就是因此而得名。由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡眠是非常必要的,自旋锁的效率远高于......
  • mysql innodb_lock_wait_timeout修改
    一、概述设置mysql事务锁超时时间innodb_lock_wait_timeoutMysql数据库采用InnoDB模式,默认参数:innodb_lock_wait_timeout设置锁等待的时间是50s,一旦数据库锁超过这个时间就会报错。二、修改1、查询SHOWVARIABLESLIKE'innodb_lock_wait_timeout';2、session级别修改SETi......
  • library cache lock故障分析
    现象客户数据库在每周五出现大量的“librarycachelock”等待事件,数据库业务办理失败。问题分析从ASH视图我们可以发现,数据库从9:01分开始出现“librarycachelock”等待事件。如上图,等待事件中P3TEXT对应的是100*mode+namespace,对于的P3RAW十六进制值为52002。namespace52转为......
  • block中真实存储的数据oracle
    概念描述通常数据库的一张表会存储number、char等等类型的数据,这些数据通过select查询就能被人所识别,但是Oracle数据库存储这些数据的时候却不会“明文”存储。如果我们能把表对应的dbf表空间文件下载下来,再通过一些转换手段将dbf中的数据块内容转换成人能识别的“明文”,但首先必须......
  • 天翼云存储资源盘活系统HBlock,全面释放企业数据价值
    9月6日,天翼云与科技媒体InfoQ联合举办的以“存储难题新解法,揭秘极/致易用的HBlock”为主题的线上技术分享会圆满落幕。天翼云国际业务事业部研发专家武志民与存储产品线总监魏玮以“天翼云存储资源盘活系统HBlock,深挖独创技术亮点与实战演练”为主题,分享了HBlock在安装部署、数据......
  • 天翼云存储资源盘活系统HBlock,全面释放企业数据价值
    9月6日,天翼云与科技媒体InfoQ联合举办的以“存储难题新解法,揭秘极致易用的HBlock”为主题的线上技术分享会圆满落幕。天翼云国际业务事业部研发专家武志民与存储产品线总监魏玮以“天翼云存储资源盘活系统HBlock,深挖独创技术亮点与实战演练”为主题,分享了HBlock在安装部署、数据可......
  • Java多线程____BlockingQueue阻塞队列使用
    packagecom.frame.base.thread;importjava.util.concurrent.BlockingQueue;importjava.util.concurrent.ArrayBlockingQueue;/***并发编程____阻塞队列*/publicclassBlockingQueueTest{ publicstaticvoidmain(String[]args)throwsInterruptedException{......
  • RSA加密 too much data for RSA block
    场景:RSA加密//RSA加密 这样处理byte[]bytes=ci.doFinal(data.getBytes(StandardCharsets.UTF_8));returnBase64.getEncoder().encodeToString(bytes);//解密时这样处理byte[]bytes=ci.doFinal(Base64.getDecoder().decode(base64Data));returnnewString(bytes);......