面试问题总结

|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
悲观锁 + 乐观锁

悲观锁(Pessimistic Lock)
每次获取数据的时候,都会担心数据被修改,所以每次操作数据前都会进行加锁(读锁、写锁、行锁等),确保在自己在使用数据过程中,数据戹被其他进程修改,使用完成后再对数据进行解锁。由于数据被上了所,期间对数据进行读写的其他进程都需等待。在Java中,synchronized的思想也是悲观锁。

乐观锁(Optimistic Lock)
每次获取数据的时候,都不会担心数据被修改,所以每次获取数据的时候都不会进行加锁,但在更新数据的时候需要判断数据是否被别人修改。如果数据被其他线程更改,就不进行数据更新。如果数据没有被其他线程更改,就进行数据更新。因为数据没有进行加锁,期间数据可以被进行读写操作。
一般会使用版本机制或CAS操作实现。

 version方式:
一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值与当前数据库中的version值相等,才更新,否则重试更新操作,直到更新成功
SQL:update table set x=x+1, version=version+1 where id=#{id} and version=#{version};
CAS操作方式:
即compare and swap 或者 compare and set,涉及到三个操作数,数据所在的内存值,预期值,新值。当需要更新时,判断当前内存值与之前取到的值是否相等,若相等,则用新值更新,若失败则重试,一般情况下是一个自旋操作,即不断的重试。

适用场景:
悲观锁:适合写操作频繁的场景。如果用于读操作频繁的场景,每次读取都进行加锁,会增加大量锁的开销,降低系统吞吐率。

乐观锁:适合读操作频繁的场景如果用于写操作频繁的场景,数据发生冲突的可能性就会增加,为例保证数据的一致性,应用层需要不断的重新获取数据,这样就带来了大量的查询操作,降低系统的吞吐率。
文章目录
|
载入天数...载入时分秒...