首页 > 其他分享 >悲观锁和乐观锁

悲观锁和乐观锁

时间:2024-07-07 09:42:03浏览次数:12  
标签:Thread System 乐观 线程 悲观 println out

在Java中,悲观锁和乐观锁是处理并发访问共享资源时采用的不同策略。它们主要的区别在于对数据竞争的预期和处理方式。

悲观锁 (Pessimistic Lock)

悲观锁基于“悲观”的假设,即默认情况下它认为数据可能会被其他线程修改,因此在操作数据前会尝试获得独占的锁。一旦某个线程持有悲观锁,其他试图访问相同资源的线程将被阻塞,直到锁被释放。

概念和作用:
悲观锁通过确保在任何时刻只有一个线程能够访问共享资源,从而避免了数据的竞争条件。它保证了数据的一致性和完整性,但是可能会降低系统的整体性能,因为等待锁的线程会被阻塞。

示例代码:

public class PessimisticLockExample {
    public static void main(String[] args) {
        Object lock = new Object();
    
        Thread thread1 = new Thread(() -> {
            synchronized (lock) { // 悲观锁
                System.out.println("Thread 1: Acquired lock");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread 1: Releasing lock");
            }
        });
    
        Thread thread2 = new Thread(() -> {
            synchronized (lock) { // 悲观锁
                System.out.println("Thread 2: Attempting to acquire lock");
            }
        });
    
        thread1.start();
        thread2.start();
    }
}

在这个例子中,thread2​在thread1​释放锁之前将被阻塞,无法执行其代码。

乐观锁 (Optimistic Lock)

乐观锁基于“乐观”的假设,即默认情况下它认为数据不会被其他线程修改,因此在操作数据时不立即加锁。当需要更新数据时,它会检查在此期间数据是否已经被其他线程修改过。如果数据未被修改,则更新成功;如果数据已被修改,则更新失败,并可能触发重试。

概念和作用:
乐观锁主要用于减少锁带来的性能开销,尤其是在读操作远多于写操作的场景下。它通过避免不必要的锁争用来提高并发性能,但这也意味着在数据确实被其他线程修改时,操作可能会失败。

实现方式:
乐观锁可以通过版本号机制或CAS(Compare and Swap)算法来实现。

示例代码:

import java.util.concurrent.atomic.AtomicInteger;

public class OptimisticLockExample {
    public static void main(String[] args) {
        AtomicInteger counter = new AtomicInteger(0); // 使用乐观锁
    
        Thread thread1 = new Thread(() -> {
            int oldValue = counter.get();
            // 假设这里有一段长的计算过程...
            int newValue = oldValue + 1;
            boolean success = counter.compareAndSet(oldValue, newValue); // CAS操作
            if (success) {
                System.out.println("Thread 1: Incremented value to " + newValue);
            } else {
                System.out.println("Thread 1: Failed to increment value.");
            }
        });
    
        Thread thread2 = new Thread(() -> {
            int oldValue = counter.get();
            // 假设这里有一段长的计算过程...
            int newValue = oldValue + 1;
            boolean success = counter.compareAndSet(oldValue, newValue); // CAS操作
            if (success) {
                System.out.println("Thread 2: Incremented value to " + newValue);
            } else {
                System.out.println("Thread 2: Failed to increment value.");
            }
        });
    
        thread1.start();
        thread2.start();
    }
}

在这个例子中,AtomicInteger​的compareAndSet​方法是一个CAS操作,它实现了乐观锁。如果两个线程同时尝试增加计数器的值,只有一个线程的更新会成功,另一个线程的更新会失败,因为它检测到数据已经发生了变化。

标签:Thread,System,乐观,线程,悲观,println,out
From: https://www.cnblogs.com/NorthPoet/p/18288221

相关文章

  • 一文带你了解乐观锁和悲观锁的本质区别!
    文章目录悲观锁是什么?乐观锁是什么?如何实现乐观锁?什么是CAS应用局限性ABA问题是什么?悲观锁是什么?悲观锁它总是假设最坏的情况,它会认为共享资源在每次被访问的时候就会出现线程安全问题,所以每次在获取资源的时候都会上锁,以避免线程安全问题发生。也就是说,共享资源每......
  • AI落地不容乐观-从神话到现实
    开篇在这儿我不是给大家泼冷水,而是我们一起来看一下从2022年11月左右GPT3.0掀起了一股“AI狂潮”后到现在,AI在商用、工业、军用下到底有没有得到了大规模应用呢?这个答案每一个参与者其实心里有数那就是:没有。但是呢它的确在一些方面如:对于个人的赋能让一个只会单一技能的人......
  • 悲观锁和乐观锁的区别
    悲观锁和乐观锁的区别悲观锁悲观锁认为数据在处理过程中的任何时候都有可能出现冲突,因此在数据读取时就对其进行锁定,防止其他事务进行修改,直到完成读取或修改后才释放锁。在关系型数据库中,通常通过使用数据库的事务和锁的机制实现悲观并发控制,例如使用SELECTFORUPDATE语句在......
  • 为什么定制人工智能让我对未来充满乐观,从创建自己的人工智能中学到了什么
    您是否曾经想过克隆自己?我不是指身体上的克隆,而是指技术上的克隆。提取您一生积累的专业知识和知识并将其“开源”。好吧,我就是这么做的!在此过程中我学到了很多东西。以下是我这样做的方法。推荐文章《如何微调NLLB-200模型以翻译新语言(教程含源码)》权重3《LLM......
  • MySQL 乐观锁
    MySQL乐观锁乐观锁认为当前的情况是最好的情况,即每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据droptableifexistssupply_address;--创建表CREATETABLEifnotexists`supply_address`(`id`int......
  • 什么是qps,tps,并发量,pv,uv、接口幂等性、悲观锁乐观锁
    它们都是衡量软件好坏的标准11.qps:QueriesPerSecond,每秒查询率,一台服务器每秒能够响应的查询次数,每秒的响应请求数2-如何估算自己项目的QPS?--取决于:并发量和平均响应时间30.1s*10=1s4-并发量:同一时刻,能并发几个,假设并发量是1......
  • 使用乐观锁和CAS解决超卖(Overselling)
    今天我要和大家分享的是如何在Java中使用乐观锁和CAS(Compare-And-Swap)技术来解决超卖的问题。最近我在项目中实现了这个功能,觉得非常有意思,所以决定分享出来。希望对大家有所帮助!背景介绍秒杀活动通常在电商平台中很常见,我觉得实现这个功能的难点在于多线程避免超卖。为了应......
  • 深入理解Redis事务、事务异常、乐观锁、管道
    Redis事务与MySQL事务不一样。原子性:MySQL有UndoLog机制,支持强原子性,和回滚。Redis只能保证事务内指令可以不被干扰的在同一批次执行,且没有机制保证全部成功则提交,部分失败则回滚。隔离性:MySQL的隔离性指多个事务可以并发执行,MySQL有MVCC机制。而Redis没有,Redis是事务提交前......
  • 互斥锁、自旋锁、读写锁、悲观锁和乐观锁
    都有哪些锁?互斥锁、自旋锁、读写锁、乐观锁、悲观锁。互斥锁与自旋锁加锁的目的就是保证共享资源在任意时间里,只有一个线程访问,这样就可以避免多线程导致共享数据错乱的问题。当已经有一个线程加锁后,其他线程加锁则就会失败,互斥锁和自旋锁对于加锁失败后的处理方式是不......
  • JPA和Hibernate的乐观锁与悲观锁
    哈喽,大家好,我是木头左!JPA和Hibernate的乐观锁和悲观锁乐观锁乐观锁是一种假设资源不会被冲突影响的并发控制策略。它假设多个事务在同一时间内不会发生冲突,因此不需要加锁。当事务提交时,如果检测到数据发生了改变,就会抛出异常,让开发者决定如何处理这个冲突。在JPA中,可以使用......