乐观锁和悲观锁

1 基本概念

悲观锁就是说,如果共享资源被别的线程占用了,那么其它所有的线程都得sleep等待。

乐观锁是说,弄一个死循环,假如共享资源被别的线程占用了,那么我就再试,死也不等待。

2 实现案例之一

java的AtomicInteger的

incrementAndGet()

实现的原理:

public final int incrementAndGet() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return next;
    }
}

其中compareAndSet由处理器提供的原子指令CMPXCHG来实现,如果这是一个单核的cpu,那么就不需要锁了,因为自带锁属性,但是如果是一个多核的cpu,那么该指令就会锁住内存,然后完成比较,如果相同,那么更新内存中的值,如果不同,那么放弃。

总体的思路是这样的。我死也不sleep等待,我不听的尝试,每次的尝试的步骤是这样的:我先获取内存中的值(多核cpu,每次只允许一个核访问同一内存,这个是硬件上保证的),然后加1,这个时候我想要更新内存了,但是,我调用CMPXCHG来进行更新,看看内存中的值是不是已经被别人更新了,如果老值等于现在的值就说明没有被更新,所以我可以更新,否则,放弃本次尝试,继续下一次的尝试。

3 数据库中的乐观锁的原理是一样的

使用乐观锁的表有一个version字段,读取数据时,该字段会被一起读出,更新数据时,将其加1,提交数据前先比较当前数据库中的版本号和新的version,如果新的version大于当前数据库的版本号就说明之前读取的数据没有过期,可以写入。这里查看当前数据库中表的版本号、比较版本号和写入数据的操作是需要加悲观锁的。只不过任何人读数据库不用加悲观锁。

原文地址:https://www.cnblogs.com/hustdc/p/8422391.html