乐观锁认为自己在修改数据时,不会有别的线程修改数据,所以不会添加锁,只会在更新数据的时候会判断有没有别的线程修改当前的数据,如果当前的数据没有被更新,则会成功的讲数据写入,如果数据已经被别的线程更新,则会根据不同的实现方式执行不同的操作:报错,自动重试
乐观锁是由CAS算法实现的,CAS是一种无锁的算法,在不适用锁的情况下实现多线程之间的变量同步.java.util.concurrent包中的元子类是通过CAS来实现乐观锁的.
CAS(比较与交换)算法涉及到3个参数:需要读写的内存值 V ,需要进行比较的值 A ,需要进行写入的新值 B
当A的值等于V的值时,CAS通过原子方式用B的值来更新V 的值("比较+更新" 整体就是原子操作),否则不会执行任何操作,一般情况下,"更新"是一个不断重试的操作
CAS虽然高效,但是也存在3个问题:
1.ABA问题:CAS需要在操作值得时候,检查内存值是否发生变化,没有变化才会更新内存值,但是如果内存值原来是A,后来变成了B,然后又变成了A,那么CAS在检查内存值的时候会发现内存值没有发生任何变化,但是其实已经发生了变化了,这就是所谓的ABA问题.ABA问题解决的思路就是在变量前添加版本号,每次变量更新的时候都把版本号+1,这样变化过程就是ABA变成了1A 2B 3A
2.循环时间长,开销大.CAS操作长时间不成功,就会导致一直自旋,给CPU带来非常大的消耗.
3.只能保证一个共享变量的原子操作.对一个共享变量执行操作的时候,CAS能够保证原子性,但是对于多个共享变量进行操作时,CAS是无法保证原子性的
悲观锁,他就很悲观,每次拿数据的时候都会认为别人会修改,所以每次拿数据的时候都会上锁,这样别人想拿到这个数据的时候就会一直等待,直到他拿到锁.
悲观锁适合写操作,先加锁,保证写入时,数据正常
乐观锁适合读操作,不加锁的特点能使其读操作的性能大幅提升.