一、背景知识
锁的作用:多个线程并发操作同一数据,保证数据的准确性。也就是说,多线程情况下,每个线程的执行结果和单线程时相同。
下面要说的乐观锁、悲观锁都是一种概念,并不是具体实现。
二、乐观锁
概念:线程读取数据时并不会上锁,但会保留当前数据的值为原有值,之后在进行修改前用原有值和现在的值进行对比,如果相同可以修改。
使用场景:读操作较多,写操作较少。
实现:CAS操作
CAS中文是比较并替换,使用三个基本操作数,内存地址V,预期值A,修改值B。
线程先去内存地址读取数据作为预期值,在回来修改数据前。先比较预期值是否和现有的值相等,相等则替换。
CAS操作会产生ABA问题。ABA问题就是,在比较预期值和现有值时,尽管预期值和现有值相等,但有可能是数据被修改为其他值又被修改回来,CAS错误的以为数据没有被修改过。
ABA问题的解决方法:添加一个版本号(version),每次提交时版本号+1,这样可以通过检查版本号是否相同判断数据是否被修改。
额外:CAS实际是调用了native方法
三、悲观锁
概念:线程每次对数据操作时,都需要获得锁,只有持有锁的线程才能对数据进行操作。
实现:java中有两个synchronized、ReentrantLock(下回分解)