Tailwind CSSTailwind CSS
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
  • 第六章:多线程与并发

第六章:多线程与并发

6.4 同步与互斥

6.4.1 同步的概念与必要性

在多线程编程中,当多个线程同时访问共享资源(如变量、文件、数据库等)时,可能会导致数据不一致或程序逻辑错误。同步(Synchronization)是一种机制,用于协调多个线程对共享资源的访问,确保线程安全(Thread Safety)。

为什么需要同步?

  • 竞态条件(Race Condition):多个线程同时修改共享数据时,最终结果依赖于线程执行的顺序。
  • 数据不一致性:由于线程交替执行,可能导致共享数据处于不一致的状态。
  • 原子性破坏:某些操作需要作为一个不可分割的单元执行,但线程切换可能导致操作被中断。

6.4.2 同步的实现方式

Java提供了多种同步机制来实现线程安全:

1. synchronized 关键字

synchronized 是Java中最基本的同步机制,可以用于方法或代码块。

  • 同步方法:

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

    锁对象是当前实例(this),同一时间只有一个线程可以执行该方法。

  • 同步代码块:

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

    可以指定锁对象(如 this 或任意对象),比同步方法更灵活。

2. ReentrantLock 类

ReentrantLock 是 java.util.concurrent.locks 包中的锁实现,提供了比 synchronized 更灵活的锁机制。

private final ReentrantLock lock = new ReentrantLock();

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

特点:

  • 可重入:同一线程可以多次获取锁。
  • 可中断:支持 lockInterruptibly() 方法。
  • 公平性:支持公平锁和非公平锁。

3. 原子类(AtomicInteger, AtomicLong 等)

Java提供了原子类(如 AtomicInteger),通过CAS(Compare-And-Swap)机制实现无锁线程安全。

private AtomicInteger count = new AtomicInteger(0);

public void increment() {
    count.incrementAndGet();
}

6.4.3 互斥与死锁

互斥(Mutual Exclusion)

互斥是指同一时间只允许一个线程访问共享资源。Java中的锁机制(如 synchronized 和 ReentrantLock)实现了互斥。

死锁(Deadlock)

死锁是指多个线程互相持有对方需要的资源,导致所有线程都无法继续执行。

死锁的四个必要条件:

  1. 互斥条件:资源一次只能被一个线程占用。
  2. 占有并等待:线程持有资源并等待其他资源。
  3. 非抢占条件:线程持有的资源不能被其他线程强行抢占。
  4. 循环等待条件:多个线程形成环形等待关系。

避免死锁的方法:

  • 避免嵌套锁:尽量减少锁的嵌套使用。
  • 按固定顺序获取锁:所有线程按相同顺序获取锁。
  • 使用超时机制:如 tryLock() 设置超时时间。

6.4.4 线程间的通信

线程间可以通过 wait()、notify() 和 notifyAll() 方法实现协作。

  • wait():释放锁并进入等待状态。
  • notify():唤醒一个等待的线程。
  • notifyAll():唤醒所有等待的线程。

示例(生产者-消费者模型):

public class SharedBuffer {
    private Queue<Integer> buffer = new LinkedList<>();
    private final int CAPACITY = 5;

    public synchronized void produce(int item) throws InterruptedException {
        while (buffer.size() == CAPACITY) {
            wait(); // 缓冲区满,等待
        }
        buffer.add(item);
        notifyAll(); // 通知消费者
    }

    public synchronized int consume() throws InterruptedException {
        while (buffer.isEmpty()) {
            wait(); // 缓冲区空,等待
        }
        int item = buffer.poll();
        notifyAll(); // 通知生产者
        return item;
    }
}

6.4.5 同步的性能考虑

同步机制虽然能保证线程安全,但可能带来性能问题:

  • 锁竞争:多个线程竞争同一把锁时,会导致线程阻塞。
  • 上下文切换:线程频繁切换会增加系统开销。

优化建议:

  • 减少锁的粒度:尽量缩小同步代码块的范围。
  • 使用读写锁(ReadWriteLock):读操作可以并发,写操作互斥。
  • 使用无锁数据结构:如 ConcurrentHashMap。

6.4.6 总结

  • 同步是多线程编程中确保线程安全的核心机制。
  • Java提供了 synchronized、ReentrantLock 和原子类等多种同步工具。
  • 避免死锁和优化同步性能是实际开发中的关键问题。
Last Updated:: 3/27/25, 12:48 PM