文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java 中悲观锁和乐观锁的定义及实现方法有哪些?(java悲观锁乐观锁定义的方法是什么)

极客之心

极客之心

2024-12-24 21:02

关注

在 Java 编程中,悲观锁(Pessimistic Lock)和乐观锁(Optimistic Lock)是两种常用的并发控制机制,用于管理对共享资源的访问。它们在不同的场景下具有各自的优势和适用范围。

一、悲观锁的定义及实现方法

悲观锁的思想是假设在并发环境下,其他线程会频繁地修改共享资源,因此在访问共享资源之前,悲观锁会先获取锁,以防止其他线程的并发修改。这种方式虽然保证了数据的一致性,但在高并发情况下,可能会导致大量的线程等待锁,降低系统的并发性能。

在 Java 中,悲观锁通常通过同步代码块(synchronized)或重入锁(ReentrantLock)来实现。

  1. 同步代码块(synchronized)

    • 同步代码块是 Java 中最基本的同步机制,它使用 synchronized 关键字来修饰一段代码块,使得在同一时刻,只有一个线程能够进入该代码块执行。
    • 以下是一个使用同步代码块实现悲观锁的示例:
      
      public class PessimisticLockExample {
      private final Object lock = new Object();

    public void performAction() { synchronized (lock) { // 在此处执行需要同步的代码 System.out.println("Thread " + Thread.currentThread().getName() + " is in critical section."); } } }

    
     - 在上述代码中,`lock` 是一个共享的对象,多个线程通过同步代码块 `synchronized (lock)` 来获取锁。只有获取到锁的线程才能进入同步代码块执行,其他线程则会被阻塞,直到锁被释放。
  2. 重入锁(ReentrantLock)

    • 重入锁是 Java 中的一种高级同步机制,它提供了与同步代码块类似的功能,但更加灵活和强大。
    • 重入锁实现了 Lock 接口,并提供了与 synchronized 相似的同步机制,例如 lock()unlock() 方法。
    • 以下是一个使用重入锁实现悲观锁的示例:
      
      import java.util.concurrent.locks.ReentrantLock;

public class PessimisticLockExampleWithReentrantLock { private final ReentrantLock lock = new ReentrantLock();

public void performAction() {
    lock.lock();
    try {
        // 在此处执行需要同步的代码
        System.out.println("Thread " + Thread.currentThread().getName() + " is in critical section.");
    } finally {
        lock.unlock();
    }
}

}

    - 在上述代码中,`lock` 是一个重入锁对象,通过调用 `lock()` 方法获取锁,在 `try` 块中执行需要同步的代码,最后在 `finally` 块中调用 `unlock()` 方法释放锁。即使在执行同步代码块的过程中抛出异常,也能确保锁被正确释放。

**二、乐观锁的定义及实现方法**

乐观锁的思想是假设在并发环境下,其他线程不会频繁地修改共享资源,因此在访问共享资源之前,乐观锁不会获取锁,而是在更新共享资源时,通过比较版本号或使用 CAS(Compare and Swap)操作来确保数据的一致性。如果在更新过程中发现数据已经被其他线程修改,则重试更新操作,直到更新成功。这种方式虽然在高并发情况下能够提高系统的并发性能,但需要额外的开销来实现版本号管理或 CAS 操作。

在 Java 中,乐观锁通常通过原子类(Atomic类)或版本号机制来实现。

1. **原子类(Atomic类)**
    - Java 中的原子类提供了一组原子操作,例如原子更新字段、原子更新数组元素等。这些原子操作是线程安全的,能够在不使用锁的情况下实现对共享资源的更新。
    - 以下是一个使用原子类实现乐观锁的示例:
```java
import java.util.concurrent.atomic.AtomicInteger;

public class OptimisticLockExample {
    private final AtomicInteger counter = new AtomicInteger(0);

    public void increment() {
        int expectedValue = counter.get();
        while (!counter.compareAndSet(expectedValue, expectedValue + 1)) {
            expectedValue = counter.get();
        }
    }

    public int getValue() {
        return counter.get();
    }
}
- 在上述代码中,`counter` 是一个原子整数,通过调用 `compareAndSet()` 方法来实现乐观锁。`compareAndSet()` 方法会先获取当前的值,然后尝试将其更新为指定的值,如果当前值没有被其他线程修改,则更新成功,否则继续重试。
  1. 版本号机制

    • 版本号机制是一种常见的乐观锁实现方式,它通过在共享资源中添加一个版本号字段,在更新共享资源时,先获取当前的版本号,然后在更新时将版本号加 1。如果在更新过程中发现版本号已经被其他线程修改,则说明数据已经被其他线程修改,需要重新获取最新的数据并更新。
    • 以下是一个使用版本号机制实现乐观锁的示例:
      
      public class OptimisticLockExampleWithVersion {
      private int data;
      private int version;

    public synchronized int getData() { return data; }

    public synchronized void updateData(int newData) { int currentVersion = version; // 模拟数据更新的延迟 try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } if (version == currentVersion) { data = newData; version++; System.out.println("Thread " + Thread.currentThread().getName() + " updated data."); } else { System.out.println("Data has been modified by other thread."); } } }

    
     - 在上述代码中,`data` 是共享的数据,`version` 是版本号字段。`updateData()` 方法在更新数据之前,先获取当前的版本号,然后在更新时将版本号加 1。如果在更新过程中发现版本号已经被其他线程修改,则说明数据已经被其他线程修改,需要重新获取最新的数据并更新。

三、总结

悲观锁和乐观锁是两种不同的并发控制机制,它们在不同的场景下具有各自的优势和适用范围。

悲观锁适用于对数据一致性要求较高的场景,例如银行转账等。在这种情况下,悲观锁能够保证在同一时刻只有一个线程能够访问共享资源,从而避免数据的不一致性。

乐观锁适用于对并发性能要求较高的场景,例如缓存更新等。在这种情况下,乐观锁能够在不获取锁的情况下实现对共享资源的更新,从而提高系统的并发性能。

在实际应用中,需要根据具体的业务需求和并发情况来选择合适的锁机制。如果对数据一致性要求较高,可以选择悲观锁;如果对并发性能要求较高,可以选择乐观锁。同时,也可以结合使用悲观锁和乐观锁,以充分发挥它们的优势。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯