Java中的线程同步 | AI生成和翻译

Home 2025.02

让我们深入探讨Java中的线程同步!当多个线程访问共享资源(如变量、集合或文件)时,需要防止竞态条件——即线程相互干扰导致不可预测的结果。Java为此提供了几种工具:synchronizedLockSemaphore。我将分别解释它们,展示示例并进行比较,以便您根据需求选择合适的方法。


1. synchronized关键字

synchronized关键字确保一次只有一个线程可以执行代码块或方法。这是最简单的同步工具,内置于Java核心中。

工作原理

示例:使用synchronized的计数器

class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);
        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println("最终计数: " + counter.getCount()); // 始终为2000
    }
}

同步块

您也可以锁定特定代码而不是整个方法:

public void increment() {
    synchronized (this) {
        count++;
    }
}

优缺点


2. Lock接口(java.util.concurrent.locks)

Lock接口(例如ReentrantLock)比synchronized提供更多控制。它是java.util.concurrent包的一部分,旨在解决synchronized的局限性。

关键特性

示例:使用ReentrantLock的计数器

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

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

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock(); // 始终在finally中解锁
        }
    }

    public int getCount() {
        return count;
    }
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);
        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println("最终计数: " + counter.getCount()); // 始终为2000
    }
}

高级特性

优缺点


3. Semaphore

Semaphore通过维护一组许可来控制对资源的访问。它非常适合限制并发性(例如最多5个线程可以访问资源)。

工作原理

示例:限制数据库连接

import java.util.concurrent.Semaphore;

class ConnectionPool {
    private final Semaphore semaphore = new Semaphore(3); // 最多3个连接

    public void connect() {
        try {
            semaphore.acquire();
            System.out.println(Thread.currentThread().getName() + " 已连接");
            Thread.sleep(1000); // 模拟工作
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            semaphore.release();
            System.out.println(Thread.currentThread().getName() + " 已断开连接");
        }
    }
}

public class Main {
    public static void main(String[] args) {
        ConnectionPool pool = new ConnectionPool();
        Runnable task = () -> pool.connect();

        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(task, "线程-" + i);
            threads[i].start();
        }
    }
}

高级特性

优缺点


ExecutorService结合使用

以下是如何在线程池中使用这些工具:

import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class SharedResource {
    private int value = 0;
    private final Lock lock = new ReentrantLock();

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

    public int getValue() {
        return value;
    }
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        SharedResource resource = new SharedResource();
        ExecutorService executor = Executors.newFixedThreadPool(4);

        for (int i = 0; i < 10; i++) {
            executor.submit(() -> {
                for (int j = 0; j < 100; j++) {
                    resource.increment();
                }
            });
        }

        executor.shutdown();
        executor.awaitTermination(5, TimeUnit.SECONDS);
        System.out.println("最终值: " + resource.getValue()); // 始终为1000
    }
}

比较

特性 synchronized Lock (ReentrantLock) Semaphore
易用性 中等
灵活性 中等
粒度 方法/块 显式 基于许可
可中断性
公平性选项
使用场景 简单互斥 高级控制 资源限制

何时使用什么?


Back Donate