一、悲观锁
悲观锁 (Pessimistic Locking),具有强烈的独占和排他特性。它指的是对数据被外界修改持保守态度。因此,在整个执行过程中,将处于锁定状态。所以,悲观锁是一种悲观思想,它总认为最坏的情况可能会出现,它认为数据很可能会被其他人所修改,所以悲观铁在持有数据的时候总会把资源 或者 数据 铁住,这样其他线程想要请求这个资源的时候就会阻塞,直到等到悲观锁把资源释放为止。Java 中的 synchronized 和 ReentrantLock 是一种悲观锁思想的实现,因为synchronzied
和 ReetrantLock 不管是否持有资源,它都会尝试去加锁。
二、乐观锁
乐观锁(Optimistic Locking) 相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。乐观锁的思想与悲观锁的思想相反,它总认为资源和数据不会被别人所修改,所以读取不会上锁,但是乐观锁在进行写入操作的时候会判断当前数据是否被修改过。Java中的stampedLock和 AtomicInteger 是一种乐观锁思想的实现。一般通过版本号控制来实现,乐观锁适用于读多写少的场景,这样可以提高程序的吞吐量。
版本号控制:一般是在数据表中加上一个数据版本号:version 字段,表示数据被修改的次数。当数据被修改时,version 值会 +1。当事务A 要更新数据时,在读取数据的同时也会读取 version 值,在提交更新时,若刚才读取到的 version 值与当前数据库中的 version 值相等时才更新,否则重试更新操作,直到更新成功。