Java各种锁的含义以及使用场景

共享锁(读锁)

如果事务对数据A添加共享锁后,其他事务只能对A添加共享锁不可以添加排它锁,他可以被多线程共同读取,但无法区修改添加删除数据,只可以被读。

排它锁(写锁)

排他锁又叫做写锁,独占锁,当事务T对数据A添加排它锁后,该事物只允许读取A和修改,其他的事务都不可以在对数据A添加锁,直到事务提交完成后。他可以保证其他事务不能读取该数据和写数据。

互斥锁

其实概念和排他锁差不多,这里可以参考互斥锁和读写锁的区别,互斥锁只允许一个线程访问近来,过程中其他线程必须等待。

悲观锁

悲观锁顾名思义,就是很悲观,当我们要操作数据的时候,会很悲观的想象可能会有其他线程会修改当前数据,所以每次操作前都会加锁,synchronized就是悲观锁。

乐观锁

就是很乐观,每次拿数据的时候认为其他人不会修改,所以不会上锁,但是拿的时候会判断其他线程是否更新过这个数据,可以使用原子引用,版本号去进行控制。乐观锁适用于读多写少的场景。这种锁可以提高吞吐量因为这样就不用线程排队了。数据库中write——condition就是这种机制还有cas。

行级锁

他通常是用于mysql数据库中,锁表中的某一行,他的开销非常大,他会减少数据库的操作冲突。加锁粒度最小。开销大加锁慢,会出现死锁

表级锁

表级锁是锁定粒度最大的锁,对整张表加锁它实现简单,资源消耗最少,被大部分mysql引擎支持。mylsam和innodb都支持表锁。表级锁分为共享锁和排他锁。发生锁冲突概率最高。

页级锁

页级锁是所粒度基于行和表中间的锁。

事务中包含的问题

脏读

脏读就是读到了无用的数据,意思就是读到了事务还没有提交的数据。
脏读又称无效数据读出(读出了脏数据)。一个事务读取另外一个事务还没有提交的数据叫脏读。

例如:事务T1修改了某个表中的一行数据,但是还没有提交,这时候事务T2读取了被事务T1修改后的数据,之后事务T1因为某种原因回滚(Rollback)了,那么事务T2读取的数据就是脏的(无效的)。

解决办法:把数据库的事务隔离级别调整到READ_COMMITTED(读提交/不可重复读)

不可重复读

在事务中,两次查询相同的数据,返回的不同的结果,造成的原因是另一个事务修改了该数据,
解决办法:把数据库的事务隔离级别调整到REPEATABLE_READ(可重复读)

幻读

当一个事务删除所有数据后,另一个事务恰好又添加一条数据,这种类似幻觉一样的叫做幻觉
解决办法:把数据库的事务隔离级别调整到SERIALIZABLE_READ(序列化执行),或者数据库使用者自己进行加锁来保证。
在这里插入图片描述数据库默认隔离级别为repeatable-read。

小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

读未提交:意思就是其他事务更改数据后,本事务也可以读到,容易造成脏读。
读已提交:只能读到已提交的数据。具体可以参考事务理解

猜你喜欢

转载自blog.csdn.net/weixin_43203363/article/details/109520214