假设我们有一个账户类 Account
,其中包含一个余额字段 balance
,我们希望使用乐观锁实现对余额的更新操作。下面是一个简单的示例代码:
package org.zyf.javabasic.thread.lock.opti;
import java.util.concurrent.atomic.AtomicReference;
/**
* @program: zyfboot-javabasic
* @description: 账户类 Account
* @author: zhangyanfeng
* @create: 2024-06-08 12:33
**/
public class Account {
private AtomicReference<Double> balance;
public Account(double initialBalance) {
this.balance = new AtomicReference<>(initialBalance);
}
public void updateBalance(double amount) {
boolean success = false;
do {
Double currentBalance = balance.get();
Double newBalance = currentBalance + amount;
success = balance.compareAndSet(currentBalance, newBalance);
} while (!success);
}
public double getBalance() {
return balance.get();
}
}
比较使用乐观锁和悲观锁(使用 synchronized 关键字)两种方式实现余额更新的性能表现:
package org.zyf.javabasic.thread.lock.opti;
/**
* @program: zyfboot-javabasic
* @description: 乐观锁和悲观锁
* @author: zhangyanfeng
* @create: 2024-06-08 12:34
**/
public class AccountPerformanceTest {
private static final int THREAD_COUNT = 100;
private static final int ITERATIONS = 1000000;
public static void main(String[] args) throws InterruptedException {
Account optimisticAccount = new Account(1000);
Account pessimisticAccount = new Account(1000);
long startTime;
long endTime;
// 测试乐观锁性能
startTime = System.currentTimeMillis();
Thread[] optimisticThreads = new Thread[THREAD_COUNT];
for (int i = 0; i < THREAD_COUNT; i++) {
Account account = new Account(1000); // 创建新的账户对象
optimisticThreads[i] = new Thread(() -> {
for (int j = 0; j < ITERATIONS; j++) {
account.updateBalance(10);
}
});
optimisticThreads[i].start();
}
for (int i = 0; i < THREAD_COUNT; i++) {
optimisticThreads[i].join();
}
endTime = System.currentTimeMillis();
System.out.println("乐观锁总耗时:" + (endTime - startTime) + " 毫秒");
System.out.println("乐观锁最终余额:" + optimisticAccount.getBalance());
// 测试悲观锁性能
startTime = System.currentTimeMillis();
Thread[] pessimisticThreads = new Thread[THREAD_COUNT];
for (int i = 0; i < THREAD_COUNT; i++) {
Account account = new Account(1000); // 创建新的账户对象
pessimisticThreads[i] = new Thread(() -> {
for (int j = 0; j < ITERATIONS; j++) {
synchronized (account) {
account.updateBalance(10);
}
}
});
pessimisticThreads[i].start();
}
for (int i = 0; i < THREAD_COUNT; i++) {
pessimisticThreads[i].join();
}
endTime = System.currentTimeMillis();
System.out.println("悲观锁总耗时:" + (endTime - startTime) + " 毫秒");
System.out.println("悲观锁最终余额:" + pessimisticAccount.getBalance());
}
}
运行结果如下:
- 乐观锁总耗时:1293 毫秒,乐观锁最终余额:1000.0
- 悲观锁总耗时:2954 毫秒,悲观锁最终余额:1000.0
根据测试结果,乐观锁的总耗时明显比悲观锁少,而且最终余额也保持了正确的值。这与乐观锁的特性相符合,因为乐观锁在读多写少的场景下性能通常会更好,而且不会导致线程阻塞,从而提高了并发性能。
转载来自于张彦峰ZYF大佬的:超越并发瓶颈:CAS与乐观锁的智慧应用_系统自动流转-CSDN博客
synchronized
是 Java 内置的同步机制,依赖 JVM 实现,通过进入和退出监视器锁(Monitor Lock)来保证线程的安全性。在高并发情况下,线程可能会频繁地在 BLOCKED
状态和 RUNNABLE
状态之间切换,导致用户态和内核态的频繁切换,从而影响性能。