建材秒知道
登录
建材号 > 链条 > 正文

共享锁(S锁)和排它锁(X锁)

灵巧的鞋垫
哭泣的凉面
2022-12-28 00:53:33

共享锁(S锁)和排它锁(X锁)

最佳答案
勤奋的流沙
眯眯眼的帆布鞋
2026-01-25 12:38:42

共享锁又称为 读锁 。即读取操作时创建的锁。其他用户可以并发的读取数据。

若事务T对数据A加上共享锁,则事务T只能读A; 其他事务也只能对数据A加共享锁,而不能加排它锁,直到事务T释放A上的S锁。

这就保证了其他事务可以读A,但是在事务T释放A上的共享锁之前,不能对A做任何修改。

若事务T对数据对象A加上排它锁,则只允许T读取和修改数据A,其他任何事务都不能再对A加任何类型的锁,直到事务T释放X锁。

它可以防止其他事务获取资源上的锁,直到事务末尾释放锁

最新回答
羞涩的棒棒糖
生动的口红
2026-01-25 12:38:42

共享锁:共享锁是读锁,是在执行读取操作的时候创建的。如果事务 T 对 数据 A 添加了共享锁,那么其他事务只能再对数据 A 添加 共享锁而不能添加其他类型的锁,对于已经添加了共享锁的事务,只能执行读操作,而不能执行写操作。共享锁的使用方式需要在查询语句后面添加 LOCK IN SHARE MODE

排它锁:排它锁是写锁,如果事务 T 对 数据 A 添加排它锁,那么其他事务就不能再添加其他类型的锁,已经添加了排它锁的事务,既能执行读操作也能执行写操作,排它锁的使用方式需要在查询语句中添加 FOR UPDATe

意向锁是表级锁,它主要用于在一个事务中表明下一行将要被请求的锁类型,INNODB 中的有两个表锁:意向共享锁、意向排它锁

意向共享锁:表明事务准备给数据行添加一个共享锁,一个数据行在被添加共享锁之前首先需要获取当前表的意向共享锁

意向排它锁:表明事务准备给数据行添加一个排它锁,一个数据行在被添加排它锁之前首先需要获取当前表的意向排它锁

意向锁是 INNODB 自动添加的,不需要用户干预

端庄的乌龟
正直的河马
2026-01-25 12:38:42

一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

常见用法

多个人等一个信号后继续执行操作。例如5个运动员,等一个发令员的枪响。

一个人等多个人的信号。旅游团等所有人签到完成才开始出发。

我们最常见见到使用的地方是zk获取连接的时候

这里了也可以看到很明确的使用方法,countDown直到0,await的线程才会继续执行。

CountDownLatch内部使用了共享锁。如果这里还不知道共享和独占的区别,可以看前面的aqs速读。

获取锁成功的方法很简单

共享锁有个约定,返回有三种情况。

共享锁在tryAcquireShared返回大于0的值的时候,会唤醒其他停顿状态加锁线程。由于没有对state的增加操作,所以当state变成0的时候,所有尝试加锁的线程都会被唤醒。

释放锁的操作,就是把state的值减一,当只有state变成0的时候,才返回true,tryReleaseShared返回true的时候会触发唤醒其他加锁线程的操作。

通过上面的过程,我们可以看到CountDownLatch中的共享锁的加锁和释放锁的过程,下面看看是如何和CountDownLatch结合的。

CountDownLatch的构造里会初始化共享锁,并且设置state的值。

countDown是释放锁,最终会调用到tryReleaseShared。

await是加锁,最终会调用到 tryAcquireShared。

CountDownLatch就是一个不断释放锁的过程。

根据业务情况,增加一个最大等待时间。使用这种方式,需要对失败的各种情况作出业务上的对应处理,否则就出现各种数据不正确的问题。也可以对countDown的线程做好异常处理,最好使用另外一个线程池来处理这些线程。这种情况就需要对业务不能停顿时间特别长,导致线程池的资源被耗光的情况做处理。如果是想通过new Thread避免,就需要考虑线程突然暴涨的问题。

热心的春天
苗条的航空
2026-01-25 12:38:42
本文使用 ReentrantLock 和 CountDownLatch 演示独占锁和共享锁的实现。

独占锁

获取锁

释放锁

共享锁

通过status标识锁

ReentrantLock使用排他锁。AQS的status>0表示加锁,thread是当前获取锁的线程。该锁时可重入锁,所以status>0。

CountDownLatch 使用共享锁。AQS的status为共享锁的标记位,status>0就是加锁,等于0就是释放锁。每调用一次countDown(),status减1。

线程会阻塞在await(),直到countDown()将status置为0

缥缈的薯片
自觉的钢笔
2026-01-25 12:38:42
“共享锁是表级的,排他锁是行级的”

==>

后半句肯定是错误的 排它锁 也可能是表级的....

共享锁 是允许别的事务读取你用共享锁锁住的表或者记录

排他锁 是不允许别的事务读取或者修改你用排他锁锁住的表或者记录

....

A 事务 执行 select * from tb没有commit 这个时候tb上加了共享锁

B 事务 可以执行 select 但是不能执行 update tb这样的操作

A事务 执行 update tb ,没有commit 这个时候tb上加了排它锁

B事务 依据他加的是表级或者行级 不允许B事务查看tb表上的数据或者部分行数据

斯文的钢铁侠
酷炫的过客
2026-01-25 12:38:42
独享锁是指该锁一次只能被一个线程所持有。

共享锁是指该锁可被多个线程所持有。

对于Java ReentrantLock而言,其是独享锁。但是对于Lock的另一个实现类ReadWriteLock,其读锁是共享锁,其写锁是独享锁。

读锁的共享锁可保证并发读是非常高效的,读写,写读 ,写写的过程是互斥的。

独享锁与共享锁也是通过AQS来实现的,通过实现不同的方法,来实现独享或者共享。

对于Synchronized而言,当然是独享锁。

淡淡的砖头
震动的乌龟
2026-01-25 12:38:42
-- Note we use tempdb for testing.USE tempdb-- Create datatable in tempdb.CREATE TABLE DlTable1 (DL1Id INT, DL1Name VARCHAr(20))CREATE TABLE DlTable2 (DL2Id INT, DL2Name VARCHAr(20))-- Insert multiple data into DlTable1 and DlTable2 in SQL Server 2005.INSERT INTO DlTable1

SELECT 1, 'Deadlock'UNIOn ALL

SELECT 2, 'JKhuang'UNIOn ALL

SELECT 3, 'Test'

GOINSERT INTO DlTable2

SELECT 1, 'Deadlock'UNIOn ALL

SELECT 2, 'JacksonHuang'UNIOn ALL

SELECT 3, 'Test'

GO-- Insert multiple data into DlTable1 and DlTable2 in SQL Server 2008.INSERT INTO DlTable1 VALUES (1, 'Deadlock'), (2, 'JKhuang'), (3, 'Test')INSERT INTO DlTable2 VALUES (1, 'Deadlock'), (2, 'JacksonHuang'), (3, 'Test')

聪明的金针菇
优美的斑马
2026-01-25 12:38:42
共享锁和独占锁不互斥。共享锁是指该锁可被多个线程所持有,独占锁是指该锁一次只能被一个线程所持有,这两个是互斥的关系,说共享锁和独占锁不互斥是错误的。共享锁和独占锁是指该锁一次只能被一个线程所持有。如果线程T对数据A加上排锁后,则其线程不能再对A加任何类型的锁。