Java如何实现互斥锁
在多线程编程中,互斥锁是一种常见的同步机制,用于保护共享资源的访问。Java提供了多种方式来实现互斥锁,包括synchronized关键字、ReentrantLock类和Semaphore类等。本文将介绍这些方法的使用方式,并提供相应的代码示例。
1. synchronized关键字
synchronized关键字是Java中最常用的实现互斥锁的方式。它可以用于修饰方法或代码块,保证在同一时间只有一个线程可以执行被synchronized修饰的代码。
示例代码:
public class SynchronizedExample {
private static int counter = 0;
public synchronized static void increment() {
counter++;
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000000; i++) {
increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000000; i++) {
increment();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Counter: " + counter);
}
}
在上述示例代码中,我们使用synchronized关键字修饰了increment()
方法。当多个线程调用该方法时,只有一个线程能够进入方法执行,从而保证了counter的递增操作的互斥性。
2. ReentrantLock类
ReentrantLock类是Java.util.concurrent包中提供的一种实现互斥锁的方式。与synchronized关键字相比,ReentrantLock提供了更灵活的同步控制,例如可中断锁、可限时等待、公平锁等。
示例代码:
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
private static int counter = 0;
private static ReentrantLock lock = new ReentrantLock();
public static void increment() {
lock.lock();
try {
counter++;
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000000; i++) {
increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000000; i++) {
increment();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Counter: " + counter);
}
}
在上述示例代码中,我们使用ReentrantLock类对increment()
方法进行同步控制。通过调用lock()
方法获取锁,并在finally块中调用unlock()
方法释放锁。这样可以确保在任何情况下锁都能被正确释放。
3. Semaphore类
Semaphore类是Java.util.concurrent包中提供的一种实现互斥锁的方式,它可以控制同时访问某个资源的线程数量。
示例代码:
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
private static int counter = 0;
private static Semaphore semaphore = new Semaphore(1);
public static void increment() throws InterruptedException {
semaphore.acquire();
try {
counter++;
} finally {
semaphore.release();
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000000; i++) {
try {
increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000000; i++) {
try {
increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Counter: " + counter);
}
}
在上述示例代码中,我们使用Semaphore类对increment()
方法进行同步控制。通过调用acquire()
方法获取信号量,当信号量计数器为0时,线程将被阻塞,直到有其他线程释放信号