共享锁(S锁)和排它锁(X锁)
共享锁又称为 读锁 。即读取操作时创建的锁。其他用户可以并发的读取数据。
若事务T对数据A加上共享锁,则事务T只能读A; 其他事务也只能对数据A加共享锁,而不能加排它锁,直到事务T释放A上的S锁。
这就保证了其他事务可以读A,但是在事务T释放A上的共享锁之前,不能对A做任何修改。
若事务T对数据对象A加上排它锁,则只允许T读取和修改数据A,其他任何事务都不能再对A加任何类型的锁,直到事务T释放X锁。
它可以防止其他事务获取资源上的锁,直到事务末尾释放锁
共享锁:共享锁是读锁,是在执行读取操作的时候创建的。如果事务 T 对 数据 A 添加了共享锁,那么其他事务只能再对数据 A 添加 共享锁而不能添加其他类型的锁,对于已经添加了共享锁的事务,只能执行读操作,而不能执行写操作。共享锁的使用方式需要在查询语句后面添加 LOCK IN SHARE MODE
排它锁:排它锁是写锁,如果事务 T 对 数据 A 添加排它锁,那么其他事务就不能再添加其他类型的锁,已经添加了排它锁的事务,既能执行读操作也能执行写操作,排它锁的使用方式需要在查询语句中添加 FOR UPDATe
意向锁是表级锁,它主要用于在一个事务中表明下一行将要被请求的锁类型,INNODB 中的有两个表锁:意向共享锁、意向排它锁
意向共享锁:表明事务准备给数据行添加一个共享锁,一个数据行在被添加共享锁之前首先需要获取当前表的意向共享锁
意向排它锁:表明事务准备给数据行添加一个排它锁,一个数据行在被添加排它锁之前首先需要获取当前表的意向排它锁
意向锁是 INNODB 自动添加的,不需要用户干预
一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
常见用法
多个人等一个信号后继续执行操作。例如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避免,就需要考虑线程突然暴涨的问题。
独占锁
获取锁
释放锁
共享锁
通过status标识锁
ReentrantLock使用排他锁。AQS的status>0表示加锁,thread是当前获取锁的线程。该锁时可重入锁,所以status>0。
CountDownLatch 使用共享锁。AQS的status为共享锁的标记位,status>0就是加锁,等于0就是释放锁。每调用一次countDown(),status减1。
线程会阻塞在await(),直到countDown()将status置为0
==>
后半句肯定是错误的 排它锁 也可能是表级的....
共享锁 是允许别的事务读取你用共享锁锁住的表或者记录
排他锁 是不允许别的事务读取或者修改你用排他锁锁住的表或者记录
....
A 事务 执行 select * from tb没有commit 这个时候tb上加了共享锁
B 事务 可以执行 select 但是不能执行 update tb这样的操作
A事务 执行 update tb ,没有commit 这个时候tb上加了排它锁
B事务 依据他加的是表级或者行级 不允许B事务查看tb表上的数据或者部分行数据
共享锁是指该锁可被多个线程所持有。
对于Java ReentrantLock而言,其是独享锁。但是对于Lock的另一个实现类ReadWriteLock,其读锁是共享锁,其写锁是独享锁。
读锁的共享锁可保证并发读是非常高效的,读写,写读 ,写写的过程是互斥的。
独享锁与共享锁也是通过AQS来实现的,通过实现不同的方法,来实现独享或者共享。
对于Synchronized而言,当然是独享锁。
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')