0
点赞
收藏
分享

微信扫一扫

java 乐观锁和悲观锁的区别

Java乐观锁和悲观锁的区别

引言

在多线程并发编程中,为了保证数据的一致性和避免出现数据竞争的问题,我们需要使用锁机制。而乐观锁和悲观锁是常用的两种锁机制。本文将介绍Java中乐观锁和悲观锁的区别以及如何实现它们。

乐观锁和悲观锁的概念

乐观锁和悲观锁是并发编程中的两个重要概念。乐观锁的思想是假设在数据的修改和提交过程中不会发生冲突,因此不加锁,而是在更新数据时进行一次判断。如果发现冲突,则进行回滚或重试。悲观锁则是假设在数据的修改和提交过程中会发生冲突,因此在访问数据之前就加上锁,保证数据操作的原子性。

乐观锁和悲观锁的区别

乐观锁 悲观锁
思想 假设没有冲突,不加锁 假设会有冲突,加锁
适用场景 冲突较少,读操作多 冲突较多,写操作多
实现方式 使用版本号或时间戳进行判断 使用synchronized、Lock等锁机制
阻塞 不会阻塞其他线程 会阻塞其他线程
性能 性能较好,适用于读操作多的场景 性能较差,适用于写操作多的场景

实现乐观锁和悲观锁的步骤

1. 乐观锁的实现步骤

public class OptimisticLockingExample {
    private int value;
    private int version;

    public void updateValue(int newValue) {
        // 读取当前版本号
        int currentVersion = version;

        // 模拟耗时操作
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 判断版本号是否发生变化
        if (currentVersion == version) {
            value = newValue;
            version++;
            System.out.println("更新成功");
        } else {
            System.out.println("更新失败,数据已被修改");
        }
    }
}

2. 悲观锁的实现步骤

public class PessimisticLockingExample {
    private int value;
    private Object lock = new Object();

    public void updateValue(int newValue) {
        // 加锁
        synchronized (lock) {
            // 模拟耗时操作
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            value = newValue;
            System.out.println("更新成功");
        }
    }
}

流程图

st=>start: 开始
op1=>operation: 读取当前版本号
op2=>operation: 模拟耗时操作
op3=>operation: 判断版本号是否发生变化
cond=>condition: 是否发生变化?
op4=>operation: 更新数据和版本号
e=>end: 结束

st->op1->op2->op3->cond
cond(yes)->op4->e
cond(no)->e

数学公式

乐观锁的判断条件:currentVersion == version

总结

乐观锁和悲观锁是并发编程中常用的两种锁机制。乐观锁假设数据操作不会发生冲突,通过版本号或时间戳进行判断和重试;悲观锁假设数据操作会发生冲突,通过加锁确保数据的原子性。在选择锁机制时需要根据具体的业务场景进行权衡,以提高程序的并发性和性能。

举报

相关推荐

0 条评论