乐观锁:每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。
悲观锁:总是悲观的认为某个线程在处理某份资源的时候,会有别的线程来修改资源,所以在资源上加锁,一旦某个线程获取该锁,别的线程想要获取该资源就会阻塞直至获取锁的线程释放该锁(独占锁 synchronzied ReentrantLock)
乐观锁的实现机制:
CAS(compareAndSet):
三个基本操作数:
V:需要读写的内存值
A:要进行比较的值
B:要修改的新值
实现步骤:
1)获取V值,并赋值给A
2)进行一系列操作后,想要把B值赋值给V值,重新获取V值,判断V 是否等于 A, 若相等则V = B, 否则重新进行上面的步骤,直至赋值成功!
缺点:
1)会出现ABA问题, 即线程1 在对V进行操作的时候,线程2先把V修改了一遍,然后又修改回的原值(V的变化:原值-》新值-》原值),线程1在比较A与V的时候,发现没有变化,就修改成功了。
2)在资源竞争激烈的情况下, CAS出现自旋的概率较大,易浪费CPU资源
ABA问题改进:
使用版本号(version)来解决ABA问题, 每次在执行数据的修改操作时,都会带上一个版本号,一旦版本号和数据的版本号一致就可以执行修改操作并对版本号执行+1
操作,否则就执行失败。
使用场景:
乐观锁适合于:多读少写
悲观锁适合于:多写