1. synchronized 关键字


synchronized 是 Java 中最基本的锁机制,它可以修饰方法或代码块。当一个线程访问被 synchronized 修饰的方法或代码块时,它会自动获取锁,其他线程必须等待该线程释放锁后才能继续访问。

示例代码


收起

java

class Counter {
    private int count = 0;

    // 同步方法
    public synchronized void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

public class SynchronizedExample {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();

        // 创建两个线程来增加计数器的值
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

        thread1.start();
        thread2.start();

        // 等待两个线程执行完毕
        thread1.join();
        thread2.join();

        // 输出最终的计数器值
        System.out.println("Final count: " + counter.getCount());
    }
}

代码解释


在上述代码中,Counter 类的 increment 方法被 synchronized 修饰,这意味着同一时间只有一个线程可以调用该方法。因此,即使有多个线程同时尝试增加计数器的值,也不会出现数据不一致的问题。

2. ReentrantLock


ReentrantLock 是 Java 并发包(java.util.concurrent.locks)中提供的一个可重入锁,它提供了比 synchronized 更灵活的锁机制。ReentrantLock 可以实现公平锁和非公平锁,并且可以手动控制锁的获取和释放。

示例代码


收起

java

import java.util.concurrent.locks.ReentrantLock;

class CounterWithLock {
    private int count = 0;
    private final ReentrantLock lock = new ReentrantLock();

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }

    public int getCount() {
        return count;
    }
}

public class ReentrantLockExample {
    public static void main(String[] args) throws InterruptedException {
        CounterWithLock counter = new CounterWithLock();

        // 创建两个线程来增加计数器的值
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

        thread1.start();
        thread2.start();

        // 等待两个线程执行完毕
        thread1.join();
        thread2.join();

        // 输出最终的计数器值
        System.out.println("Final count: " + counter.getCount());
    }
}

代码解释


在上述代码中,CounterWithLock 类使用 ReentrantLock 来保护计数器的增加操作。在 increment 方法中,线程首先调用 lock.lock() 方法获取锁,然后执行计数器的增加操作,最后在 finally 块中调用 lock.unlock() 方法释放锁,以确保无论是否发生异常,锁都会被释放。

3. ReadWriteLock


ReadWriteLock 是 Java 并发包中提供的一种读写锁机制,它将锁分为读锁和写锁。多个线程可以同时获取读锁,但只有一个线程可以获取写锁,并且在写锁被获取时,其他线程不能获取读锁或写锁。这种机制可以提高并发性能,适用于读多写少的场景。

示例代码


收起

java

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

class Data {
    private int value;
    private final ReadWriteLock lock = new ReentrantReadWriteLock();

    public int read() {
        lock.readLock().lock();
        try {
            return value;
        } finally {
            lock.readLock().unlock();
        }
    }

    public void write(int newValue) {
        lock.writeLock().lock();
        try {
            value = newValue;
        } finally {
            lock.writeLock().unlock();
        }
    }
}

public class ReadWriteLockExample {
    public static void main(String[] args) {
        Data data = new Data();

        // 读线程
        Thread readThread1 = new Thread(() -> {
            System.out.println("Read value: " + data.read());
        });

        Thread readThread2 = new Thread(() -> {
            System.out.println("Read value: " + data.read());
        });

        // 写线程
        Thread writeThread = new Thread(() -> {
            data.write(100);
            System.out.println("Write operation completed.");
        });

        readThread1.start();
        readThread2.start();
        writeThread.start();
    }
}

代码解释


在上述代码中,Data 类使用 ReentrantReadWriteLock 来实现读写锁机制。read 方法使用读锁,多个线程可以同时调用该方法;write 方法使用写锁,同一时间只有一个线程可以调用该方法。