总结
先抛出我的结论:用CAS方式获取锁的,并非都是乐观锁。
我们在Java里使用的各种锁,几乎全都是悲观锁。synchronized从偏向锁、轻量级锁到重量级锁,全是悲观锁。JDK提供的Lock实现类全是悲观锁。其实只要有“锁对象”出现,那么就一定是悲观锁。因为乐观锁不是锁,而是一个在循环里尝试CAS的算法。
那JDK并发包里到底有没有乐观锁呢?有。java.util.concurrent.atomic包里面的原子类都是利用乐观锁实现的。 原子类AtomicInteger的自增方法为乐观锁策略
为什么网上有些资料认为偏向锁、轻量级锁是乐观锁?理由是它们底层用到了CAS?或者是把“乐观/悲观”与“轻量/重量”搞混了?其实,线程在抢占这些锁的时候,确实是循环+CAS的操作,感觉好像是乐观锁。
但问题的关键是,我们说一个锁是悲观锁还是乐观锁,总是应该站在应用层,看它们是如何锁住应用数据的,而不是站在底层看抢占锁的过程。
如果一个线程尝试获取锁时,发现已经被占用,它是否继续读取数据,等后续要更新时再决定要不要重试?对于偏向锁、轻量级锁来说,显然答案是否定的。无论是挂起还是忙等,对应用数据的读取操作都被“挡住”了。从这个角度看,它们确实是悲观锁。