侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

使用两个线程交替打印奇偶数

2025-12-13 / 0 评论 / 4 阅读

题目

使用两个线程交替打印奇偶数

信息

  • 类型:问答
  • 难度:⭐

考点

线程创建,线程同步,线程间通信

快速回答

实现两个线程交替打印奇偶数的核心要点:

  • 创建两个线程分别处理奇数和偶数打印
  • 使用synchronized关键字实现线程同步
  • 通过wait()notify()实现线程间通信
  • 共享计数器变量控制打印范围
## 解析

原理说明

该题目考察多线程协作的基本原理:
1. 两个线程共享一个计数器变量
2. 通过synchronized锁定共享对象保证原子性
3. 使用wait()让当前线程释放锁并等待
4. 使用notify()唤醒等待线程继续执行

代码示例

public class AlternatePrinting {
    private static final Object lock = new Object();
    private static int count = 1;
    private static final int MAX = 10;

    public static void main(String[] args) {
        // 奇数线程
        new Thread(() -> {
            synchronized (lock) {
                while (count <= MAX) {
                    if (count % 2 == 1) {
                        System.out.println("奇数线程: " + count++);
                        lock.notify();  // 唤醒偶数线程
                    } else {
                        try {
                            lock.wait();  // 释放锁等待
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();

        // 偶数线程
        new Thread(() -> {
            synchronized (lock) {
                while (count <= MAX) {
                    if (count % 2 == 0) {
                        System.out.println("偶数线程: " + count++);
                        lock.notify();  // 唤醒奇数线程
                    } else {
                        try {
                            lock.wait();  // 释放锁等待
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();
    }
}

最佳实践

  • 使用专用锁对象(如private static final Object lock)而非this
  • 循环检查条件(while代替if)防止虚假唤醒
  • 明确限定共享变量的操作范围(如count仅在同步块内访问)
  • 添加终止条件(count <= MAX)避免无限循环

常见错误

  • 忘记唤醒:执行后未调用notify()导致线程永久等待
  • 错误锁对象:在wait()/notify()中使用不同锁对象
  • 条件判断缺陷:使用if判断条件可能引发虚假唤醒问题
  • 同步范围过大:将整个run()方法同步导致性能下降

扩展知识

  • Lock/Condition:Java 5+可使用ReentrantLockCondition实现更灵活的线程通信
  • volatile变量:保证共享变量的可见性(但无法保证复合操作原子性)
  • 线程状态wait()会使线程进入WAITING状态,notify()将其唤醒为BLOCKED状态
  • 生产消费者模式:本题是生产者消费者模式的简化变种,核心思想相同