悲观锁与乐观锁详细讲解

悲观锁和乐观锁是并发编程中常用的两种锁机制,用于解决多线程环境下的数据竞争问题。

  1. 悲观锁 :(Pessimistic Locking)
    • 悲观锁的思想是,认为在并发环境下,数据很可能会发生冲突,因此默认情况下将数据锁住,其他线程要访问该数据时需要先获取锁才能进行操作。
    • 在 Java 中,悲观锁的实现通常使用 synchronized 关键字或 ReentrantLock 类。这些锁会在进入临界区之前先获取锁,如果无法获取到锁,线程会被阻塞等待。
    • 悲观锁保证了数据的一致性和安全性,但由于加锁的开销较大,并发性能相对较低。

悲观锁的示例代码,使用 synchronized 关键字实现:

public class TestPessimisticLock {
    private int count = 0;
    
    public synchronized void increment() {
        count++;
    }
    
    public synchronized int getCount() {
        return count;
    }
}

// 使用悲观锁的示例
TestPessimisticLock lock = new TestPessimisticLock();

for (int i = 0; i < 1000; i++) {
    new Thread(() -> {
        lock.increment();
    }).start();
}

Thread.sleep(1000);
System.out.println(lock.getCount()); // 输出 1000
  1. 乐观锁(Optimistic Locking):
    • 乐观锁的思想是,认为在并发环境下,数据冲突的可能性较小,因此不需要加锁,可以直接进行操作。当要更新数据时,先读取数据并记录版本号,然后再尝试更新。如果期间没有其他线程修改数据,则更新成功,否则需要进行重试。
    • 在 Java 中,乐观锁的实现通常使用 CAS(Compare and Swap)操作,例如使用 AtomicInteger 类或 AtomicReference 类来实现自旋锁。
    • 乐观锁的优势在于没有加锁的开销,适用于读多写少的场景,可以提高并发性能。但如果并发冲突较多,会导致频繁的重试,降低性能。
选择悲观锁还是乐观锁需要根据具体的业务场景和数据访问模式来确定。如果并发冲突较少且读操作频繁,可以考虑使用乐观锁。如果并发冲突较多或对数据一致性要求较高,可以选择悲观锁。

你可能感兴趣的:(java,java)