悲观锁:总是假设每次操作都会发生冲突,所以为了防止冲突的产生,在每次对数据进行操作的时候,都会上锁,阻塞其他进程的访问,所以悲观锁具有很强的独占性和排他性。悲观锁的实现往往依靠数据库的锁机制实现,只有这样才能保证排他性。
在某个资源不可用的时候,就将cpu让出,把当前等待线程切换为阻塞状态。等到资源(比如一个共享数据)可用了,那么就将线程唤醒,让他进入runnable状态等待cpu调度。这就是典型的悲观锁的实现。独占锁是一种悲观锁,synchronized就是一种独占锁,它假设最坏的情况,并且只有在确保其它线程不会造成干扰的情况下执行,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁。但是,线程间的切换会需要额外的开销。所以就有了悲观锁机制。
乐观锁:我们假设每次操作都不会发生并发冲突,只在提交操作时检查是否违反数据完整性。相对于悲观锁而言,乐观锁不依赖数据库的锁机制,一般而言,使用版本号实现乐观锁。另外还有
CAS。
版本号实现乐观锁原理:通常在数据库表中增加一个version字段,每次对数据进行更新操作都对version进行加1操作,之后进行的的更新操作将会检查version是否与数据库中的version相匹配。
synchronized实现悲观锁:
1、方法中使用
synchronized关键字
2、在代码块中使用synchronized关键字
除了使用synchronized关键字外,还可以使用ReentrantLock来实现同步互斥,实现悲观锁机制。不同于
synchronized,ReentrantLock是在代码层面实现的