有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步, 认准 https://blog.zysicyj.top
在 Java 中,有几种方式可以实现对某个变量的锁定:
- 使用 synchronized 关键字:synchronized 关键字是 Java 中最常用的实现锁的方式之一。通过在方法或代码块中使用 synchronized 关键字,可以确保同一时间只有一个线程可以访问被锁定的变量或代码块。例如:
1 2 3 4 5 6 7 8 9 10 11
| synchronized void synchronizedMethod() { }
void someMethod() { synchronized (this) { } }
|
使用 ReentrantLock 类:ReentrantLock 是 Java 提供的一个可重入锁实现类。与 synchronized 关键字相比,ReentrantLock 提供了更多的灵活性和功能,例如可定时的、可中断的、公平的锁等。使用 ReentrantLock 可以通过 lock()
和 unlock() 方法来手动控制对变量的锁定和释放。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13
| import java.util.concurrent.locks.ReentrantLock;
ReentrantLock lock = new ReentrantLock();
void someMethod() { lock.lock(); try { } finally { lock.unlock(); } }
|
- 使用 Atomic 类:Java 提供了一系列的原子类,如 AtomicInteger、AtomicLong 等,它们提供了一种线程安全的方式来操作变量。这些原子类使用了底层的 CAS(Compare
and Swap)操作,可以实现对变量的原子性操作,避免了使用锁的开销。例如:
1 2 3 4 5 6 7
| import java.util.concurrent.atomic.AtomicInteger;
AtomicInteger counter = new AtomicInteger();
void increment() { counter.incrementAndGet(); }
|
- 使用 volatile 关键字:volatile 关键字用于修饰变量,确保对该变量的读写操作具有可见性,即一个线程对该变量的修改对其他线程是可见的。虽然 volatile 关键字不能实现像锁那样的互斥访问,但它可以用于确保变量的一致性。例如:
1 2 3 4 5 6 7 8 9 10 11 12
| volatile boolean flag = false;
void someMethod() { flag = true; }
void anotherMethod() { if (flag) { } }
|
使用 Lock 接口的实现类:除了 ReentrantLock,Java 还提供了其他实现了 Lock 接口的类,如 ReadWriteLock、StampedLock 等。这些类提供了更多的锁定机制和功能,例如读写锁、乐观锁等。根据具体的需求,可以选择合适的 Lock 实现类来实现对变量的锁定。
使用 synchronized 关键字的 Lock 对象:除了使用 synchronized 关键字锁定方法或代码块外,还可以使用 synchronized 关键字锁定一个特定的对象,即使用 synchronized 关键字的 Lock 对象。这种方式可以更细粒度地控制对变量的锁定。例如:
1 2 3 4 5 6 7 8
| Object lock = new Object();
void someMethod() { synchronized (lock) { } }
|
除了前面提到的方式,还有其他一些方式可以在 Java 中对变量进行锁定:
- 使用 ReadWriteLock 接口:ReadWriteLock 接口提供了读写锁的机制,允许多个线程同时读取共享变量,但只允许一个线程进行写操作。这种方式可以提高并发性能,适用于读多写少的场景。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
ReadWriteLock lock = new ReentrantReadWriteLock();
void readMethod() { lock.readLock().lock(); try { } finally { lock.readLock().unlock(); } }
void writeMethod() { lock.writeLock().lock(); try { } finally { lock.writeLock().unlock(); } }
|
- 使用 Semaphore 类:Semaphore 是一个计数信号量,可以用于控制同时访问某个资源的线程数量。通过设置 Semaphore 的许可数量,可以限制对变量的并发访问。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import java.util.concurrent.Semaphore;
Semaphore semaphore = new Semaphore(1);
void someMethod() { try { semaphore.acquire(); } catch (InterruptedException e) { } finally { semaphore.release(); } }
|
除了前面提到的方式,还有一些其他的方式可以在 Java 中对变量进行锁定:
- 使用 StampedLock 类:StampedLock 是 Java
8 引入的一种乐观读写锁机制。它提供了一种优化的读写锁实现,允许多个线程同时读取共享变量,但只允许一个线程进行写操作。StampedLock 使用乐观锁和版本号的概念,可以提供更高的并发性能。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import java.util.concurrent.locks.StampedLock;
StampedLock lock = new StampedLock();
void readMethod() { long stamp = lock.tryOptimisticRead(); if (!lock.validate(stamp)) { stamp = lock.readLock(); try { } finally { lock.unlockRead(stamp); } } }
void writeMethod() { long stamp = lock.writeLock(); try { } finally { lock.unlockWrite(stamp); } }
|
- 使用 Condition 接口:Condition 接口是与锁相关联的条件,可以用于实现更复杂的线程通信和同步。通过使用 Condition,可以在特定条件下对变量进行等待和唤醒操作。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock;
ReentrantLock lock = new ReentrantLock(); Condition condition = lock.newCondition();
void awaitMethod() throws InterruptedException { lock.lock(); try { condition.await(); } finally { lock.unlock(); } }
void signalMethod() { lock.lock(); try { condition.signal(); } finally { lock.unlock(); } }
|