1. synchronized (内置锁/监视器锁)
- 场景: 适用于简单的同步需求,比如方法或代码块级别的同步。
- 特点: 隐式获取和释放锁,可重入,非公平,默认情况下可能导致线程阻塞。
- 代码示例:
Java
1public class Counter {
2 private int count = 0;
3
4 public synchronized void increment() {
5 count++;
6 }
7
8 public synchronized int getCount() {
9 return count;
10 }
11}
2. ReentrantLock (可重入锁 - JUC包提供)
- 场景: 当需要更细粒度的控制,如公平锁、尝试获取锁、锁打断等特性时使用。
- 特点: 显式获取和释放锁,支持公平锁和非公平锁,可重入。
- 代码示例:
Java
1import java.util.concurrent.locks.ReentrantLock;
2
3public class Counter {
4 private final ReentrantLock lock = new ReentrantLock();
5 private int count = 0;
6
7 public void increment() {
8 lock.lock();
9 try {
10 count++;
11 } finally {
12 lock.unlock();
13 }
14 }
15
16 public int getCount() {
17 lock.lock();
18 try {
19 return count;
20 } finally {
21 lock.unlock();
22 }
23 }
24}
3. ReadWriteLock (读写锁 - JUC包提供)
- 场景: 当存在大量的读操作和少量的写操作时,为了提高并发效率。
- 特点: 提供读锁(共享锁)和写锁(独占锁),允许多个读锁同时存在,但写锁与其他锁互斥。
- 代码示例:
Java
1import java.util.concurrent.locks.ReadWriteLock;
2import java.util.concurrent.locks.ReentrantReadWriteLock;
3
4public class DataContainer {
5 private final ReadWriteLock lock = new ReentrantReadWriteLock();
6 private volatile String data;
7
8 public void writeData(String newData) {
9 lock.writeLock().lock();
10 try {
11 data = newData;
12 } finally {
13 lock.writeLock().unlock();
14 }
15 }
16
17 public String readData() {
18 lock.readLock().lock();
19 try {
20 return data;
21 } finally {
22 lock.readLock().unlock();
23 }
24 }
25}
4. StampedLock (JUC包提供)
- 场景: 提供了读写锁的功能,还增加了乐观读锁和升级降级锁的功能,适用于复杂的并发控制场景。
- 特点: 支持读、写、乐观读等多种模式,具有更高的灵活性但使用复杂度也较高。
- 代码示例:
Java
1import java.util.concurrent.locks.StampedLock;
2
3public class Point {
4 private double x, y;
5 private final StampedLock sl = new StampedLock();
6
7 void move(double deltaX, double deltaY) {
8 long stamp = sl.writeLock();
9 try {
10 x += deltaX;
11 y += deltaY;
12 } finally {
13 sl.unlockWrite(stamp);
14 }
15 }
16
17 double distanceFromOrigin() {
18 long stamp = sl.tryOptimisticRead();
19 double currentX = x, currentY = y;
20 if (!sl.validate(stamp)) {
21 stamp = sl.readLock();
22 try {
23 currentX = x;
24 currentY = y;
25 } finally {
26 sl.unlockRead(stamp);
27 }
28 }
29 return Math.sqrt(currentX * currentX + currentY * currentY);
30 }
31}
5.乐观锁/悲观锁(概念层面,非具体Java类,但在编程逻辑中体现)
-
- 悲观锁: 认为并发操作一定会冲突,直接加锁阻止其他线程访问,如数据库行锁。
- 乐观锁: 认为并发操作不会冲突,仅在提交更新时检查数据版本,如使用版本号或时间戳验证数据是否被修改。
Java
1public class OptimisticCounter {
2 private int value;
3 private int version;
4
5 public synchronized boolean incrementIfUnchanged() {
6 if (version != Thread.currentThread().getVersion()) {
7 return false; // 数据已被修改
8 }
9 value++;
10 version++;
11 return true;
12 }
13
14 // 版本号获取逻辑需自行实现,此处简化处理
15 public int getVersion() {
16 return version;
17 }
18}