在Java编程中,使用多线程可以提高程序的性能和响应能力。然而,多线程编程也带来了线程安全性等一系列问题。为了保证线程间的正确同步和协作,我们需要使用一些常见的多线程同步技巧。本文将介绍一些常见的Java多线程同步技巧,并提供一些示例代码。
1. synchronized关键字
synchronized关键字用于保护临界区,以确保同一时间只有一个线程能够访问临界资源。在方法级别使用synchronized关键字可以确保整个方法是线程安全的,也可以在代码块中使用synchronized关键字来同步特定的代码片段。
示例代码:
public class Counter {
private int count = 0;
// synchronized修饰方法
public synchronized void increment() {
count++;
}
// synchronized修饰代码块
public void decrement() {
synchronized (this) {
count--;
}
}
}
2. volatile关键字
volatile关键字用于确保可见性和禁止指令重排。当一个变量被声明为volatile时,它的值将直接从主存中读取,而不是从线程的本地缓存中读取。
示例代码:
public class MyRunnable implements Runnable {
private volatile boolean flag = true;
public void run() {
while (flag) {
// do something
}
}
public void stop() {
flag = false;
}
}
3. ReentrantLock
ReentrantLock是一个可重入的互斥锁,与synchronized关键字相比,它提供了更灵活的锁定方式。使用ReentrantLock可以通过调用lock()方法获取锁并通过调用unlock()方法释放锁。
示例代码:
import java.util.concurrent.locks.ReentrantLock;
public class Counter {
private int count = 0;
private ReentrantLock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
}
4. Condition
Condition接口提供了更高级的线程同步机制。它允许线程在满足特定条件时暂停执行(通过调用await()方法),并在条件变为真时恢复执行(通过调用signal()或signalAll()方法)。
示例代码:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyBoundedBuffer<E> {
private Object[] items;
private int count;
private int putIndex;
private int takeIndex;
private Lock lock = new ReentrantLock();
private Condition notFull = lock.newCondition();
private Condition notEmpty = lock.newCondition();
public void put(E item) throws InterruptedException {
lock.lock();
try {
while (count == items.length) {
notFull.await();
}
items[putIndex] = item;
if (++putIndex == items.length) {
putIndex = 0;
}
count++;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public E take() throws InterruptedException {
lock.lock();
try {
while (count == 0) {
notEmpty.await();
}
E item = (E) items[takeIndex];
if (++takeIndex == items.length) {
takeIndex = 0;
}
count--;
notFull.signal();
return item;
} finally {
lock.unlock();
}
}
}
5. ConcurrentHashMap
ConcurrentHashMap是Java中线程安全的哈希表实现。它通过将数据分割成多个片段来实现高并发性能,并使用锁分段技术来控制同一时间只有一个线程可以访问同一分段。
示例代码:
import java.util.concurrent.ConcurrentHashMap;
public class MyCache {
private ConcurrentHashMap<String, Object> cache = new ConcurrentHashMap<>();
public Object get(String key) {
return cache.get(key);
}
public void put(String key, Object value) {
cache.put(key, value);
}
public void remove(String key) {
cache.remove(key);
}
}
以上是一些常见的Java多线程同步技巧的示例代码。当编写多线程程序时,需要谨慎考虑线程安全性,并选择合适的同步机制来保证线程间的正确同步和协作。
本文来自极简博客,作者:红尘紫陌,转载请注明原文链接:Java并发编程实践