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时,线程将被阻塞,直到有其他线程释放信号