JDK 8 Exchanger 源码详解(详细注释版)

JDK 8 Exchanger源码详解与特性分析

JDK 8 Exchanger 源码详解(详细注释版)

1. 类定义和基本属性

public class Exchanger<V> implements java.io.Serializable {
    
    // 序列化版本号
    private static final long serialVersionUID = -3223113410248163686L;

    /**
     * Exchanger的核心设计思想:
     * 
     * 1. 对称数据交换:
     *    - 两个线程通过Exchanger交换数据
     *    - 提供原子性的数据交换操作
     *    - 支持阻塞和超时等待
     * 
     * 2. 高效的交换机制:
     *    - 使用CAS操作实现无锁化
     *    - 支持多槽位减少竞争
     *    - 优化的内存布局
     * 
     * 3. 线程安全:
     *    - 所有操作都是线程安全的
     *    - 支持高并发环境
     *    - 无死锁风险
     * 
     * 4. 灵活的等待机制:
     *    - 支持无限期等待
     *    - 支持可中断等待
     *    - 支持超时等待
     *    - 提供多种等待选项
     * 
     * 5. 内存优化:
     *    - 使用ThreadLocal减少竞争
     *    - 优化的对象创建和回收
     *    - 及时的垃圾回收
     * 
     * 适用场景:
     * - 生产者-消费者模式的数据交换
     * - 线程间的数据传递
     * - 需要双向数据交换的场景
     * - 实现管道或通道的场景
     * - 需要原子性数据交换的场景
     */

2. 内部节点类(详细注释)

    /**
     * 线程本地节点,用于存储线程的交换信息
     * 每个线程都有自己的Node实例,减少竞争
     */
    static final class Node {
        /**
         * 要交换的数据
         * 当前线程要传递给对方线程的数据
         */
        Object item;

        /**
         * 从对方线程接收到的数据
         * 交换完成后存储对方线程传递的数据
         */
        volatile Object data;

        /**
         * 匹配的线程节点
         * 指向与当前线程进行交换的对方线程节点
         */
        volatile Node match;

        /**
         * 线程等待时的自旋次数
         * 用于控制自旋等待的时间
         */
        volatile int spins;

        /**
         * 等待队列中的下一个节点
         * 形成等待队列的链表结构
         */
        volatile Node next;

        /**
         * 等待队列中的前一个节点
         * 用于双向链表操作
         */
        volatile Node prev;

        /**
         * 线程关联的Exchanger实例
         * 用于跨Exchanger实例的区分
         */
        volatile Exchanger<?> owner;

        /**
         * 构造方法
         * @param item 要交换的数据
         */
        Node(Object item) {
            this.item = item;
        }

        /**
         * 构造方法(用于槽位节点)
         * @param owner 关联的Exchanger实例
         */
        Node(Exchanger<?> owner) {
            this.owner = owner;
        }
    }

    /**
     * 槽位节点数组
     * 用于减少线程竞争,提高并发性能
     * 通过哈希分布将线程分散到不同的槽位
     */
    private volatile Node[] arena;

    /**
     * 槽位数量的位移量
     * 用于计算哈希索引
     */
    private static final int ASHIFT = 7;

    /**
     * 槽位数量掩码
     * 用于计算哈希索引
     */
    private static final int MMASK = 0x7f;

    /**
     * 最大槽位数量
     * 限制槽数组的大小
     */
    private static final int FULL = 0x80;

    /**
     * 线程本地变量,用于存储每个线程的节点
     * 减少对象创建和垃圾回收的开销
     */
    private final ThreadLocal<Node> participant = new ThreadLocal<Node>() {
        protected Node initialValue() {
            return new Node(null);
        }
    };

    /**
     * 获取线程本地节点
     * @return 当前线程的节点
     */
    private Node newNode(Object item) {
        Node n = participant.get();
        n.item = item;
        n.data = null;
        n.match = null;
        n.spins = 0;
        n.next = null;
        n.prev = null;
        n.owner = this;
        return n;
    }

    /**
     * 重置线程本地节点
     * @param n 要重置的节点
     */
    private void reuseNode(Node n) {
        n.item = null;
        n.data = null;
        n.match = null;
        n.spins = 0;
        n.next = null;
        n.prev = null;
        n.owner = this;
    }

3. 核心交换方法(详细注释)

    /**
     * 交换数据
     * 当前线程会阻塞直到另一个线程调用exchange方法
     * 
     * 交换过程:
     * 1. 创建当前线程的节点
     * 2. 寻找匹配的线程节点
     * 3. 如果找到匹配节点,进行数据交换
     * 4. 如果没有找到匹配节点,进入等待状态
     * 5. 被匹配线程唤醒后完成数据交换
     * 6. 返回从对方线程接收到的数据
     * 
     * 阻塞特性:
     * - 如果没有其他线程等待,当前线程会阻塞
     * - 直到另一个线程调用exchange方法
     * - 交换完成后两个线程同时返回
     * 
     * 时间复杂度:O(1) 平均情况,O(∞) 最坏情况(等待时间)
     * 线程安全性:完全线程安全
     * 
     * @param x 要交换的数据
     * @return 从对方线程接收到的数据
     * @throws InterruptedException 如果线程被中断
     * 
     * 使用场景:
     * - 生产者-消费者数据交换
     * - 线程间的数据传递
     * - 实现管道或通道
     * - 需要原子性数据交换的场景
     */
    public V exchange(V x) throws InterruptedException {
        // 如果线程被中断,直接抛出异常
        if (Thread.interrupted())
            throw new InterruptedException();
        
        // 创建当前线程的节点
        Node n = newNode(x);
        // 调用核心交换方法
        Object v = doExchange(n, false, 0);
        
        // 如果返回的是中断标记,抛出异常
        if (v == n)
            throw new InterruptedException();
        
        // 返回从对方线程接收到的数据
        @SuppressWarnings("unchecked")
        V vv = (V) v;
        return vv;
    }

    /**
     * 交换数据(带超时)
     * 当前线程会在指定时间内等待另一个线程调用exchange方法
     * 
     * 超时处理:
     * 1. 创建当前线程的节点
     * 2. 寻找匹配的线程节点
     * 3. 如果找到匹配节点,进行数据交换
     * 4. 如果没有找到匹配节点,进入等待状态
     * 5. 在指定时间内等待匹配线程
     * 6. 超时后如果仍没有匹配线程,抛出TimeoutException
     * 7. 被匹配线程唤醒后完成数据交换
     * 
     * 时间处理:
     * - 将时间单位转换为纳秒
     * - 使用高精度计时
     * - 支持任意时间单位
     * 
     * 时间复杂度:O(1) 平均情况,O(∞) 最坏情况(等待时间)
     * 线程安全性:完全线程安全
     * 
     * @param x 要交换的数据
     * @param timeout 等待时间
     * @param unit 时间单位
     * @return 从对方线程接收到的数据
     * @throws InterruptedException 如果线程被中断
     * @throws TimeoutException 如果等待超时
     * 
     * 使用场景:
     * - 带超时的生产者-消费者数据交换
     * - 避免无限期等待
     * - 实现超时控制
     * - 需要时间限制的数据交换
     */
    public V exchange(V x, long timeout, TimeUnit unit)
        throws InterruptedException, TimeoutException {
        // 如果线程被中断,直接抛出异常
        if (Thread.interrupted())
            throw new InterruptedException();
        
        // 创建当前线程的节点
        Node n = newNode(x);
        // 转换超时时间为纳秒
        Object v = doExchange(n, true, unit.toNanos(timeout));
        
        // 如果返回的是中断标记,抛出异常
        if (v == n)
            throw new InterruptedException();
        // 如果返回的是超时标记,抛出超时异常
        else if (v == TIMED_OUT)
            throw new TimeoutException();
        
        // 返回从对方线程接收到的数据
        @SuppressWarnings("unchecked")
        V vv = (V) v;
        return vv;
    }

    /**
     * 超时标记
     * 用于标识超时情况
     */
    private static final Object TIMED_OUT = new Object();

    /**
     * 中断标记
     * 用于标识中断情况
     */
    private static final Object INTERRUPTED = new Object();

4. 核心交换实现(详细注释)

    /**
     * 实际的交换操作
     * 实现Exchanger的核心交换逻辑
     * 
     * 交换算法:
     * 1. 使用多槽位机制减少竞争
     * 2. 通过哈希分布将线程分散到不同槽位
     * 3. 在槽位中寻找匹配的线程节点
     * 4. 如果找到匹配节点,进行数据交换
     * 5. 如果没有找到匹配节点,进入等待状态
     * 6. 被匹配线程唤醒后完成数据交换
     * 
     * 多槽位优势:
     * - 减少线程竞争
     * - 提高并发性能
     * - 优化内存访问局部性
     * - 支持更高的吞吐量
     * 
     * @param node 当前线程的节点
     * @param timed 是否使用超时
     * @param nanos 超时时间(纳秒)
     * @return 交换结果
     */
    private Object doExchange(Node node, boolean timed, long nanos) {
        // 获取当前线程
        Thread me = Thread.currentThread();
        // 获取槽位数组
        Node[] a = arena;
        // 计算哈希索引
        int index = hashIndex();
        // 自旋次数
        int spins = SPINS;
        
        // 无限循环,直到交换完成
        for (;;) {
            // 如果槽位数组为空,初始化
            if (a == null) {
                a = arena = new Node[MMASK + 1];
                index = hashIndex();
            }
            
            // 获取槽位中的节点
            Node slot = a[index];
            
            // 如果槽位为空
            if (slot == null) {
                // 尝试将当前节点放入槽位
                if (compareAndSetSlot(a, index, null, node)) {
                    // 成功放入槽位,等待匹配
                    return awaitMatch(node, timed, nanos);
                }
            }
            // 如果槽位中的节点属于其他Exchanger实例
            else if (slot.owner != this) {
                // 创建新的槽位数组
                a = arena = new Node[MMASK + 1];
                index = hashIndex();
            }
            // 如果槽位中有等待的节点
            else if (spins > 0) {
                // 自旋等待
                spins = decrementSpins(spins);
            }
            // 如果槽位中有等待的节点且自旋结束
            else {
                // 尝试与槽位中的节点进行交换
                if (slot != node && tryMatch(slot, node)) {
                    // 交换成功,返回结果
                    return node.data;
                }
                // 如果槽位满了
                else if (a[FULL] != null) {
                    // 等待槽位空闲
                    return awaitMatch(node, timed, nanos);
                }
                // 将当前节点放入槽位
                else if (compareAndSetSlot(a, index, slot, node)) {
                    // 等待匹配
                    return awaitMatch(node, timed, nanos);
                }
            }
        }
    }

    /**
     * 计算哈希索引
     * 通过线程ID计算哈希值,将线程分散到不同槽位
     * @return 哈希索引
     */
    private int hashIndex() {
        // 获取线程ID的低7位作为哈希索引
        return (int) (Thread.currentThread().getId() & MMASK);
    }

    /**
     * CAS操作更新槽位
     * @param a 槽位数组
     * @param i 索引
     * @param cmp 预期值
     * @param val 新值
     * @return 如果更新成功返回true,否则返回false
     */
    private boolean compareAndSetSlot(Node[] a, int i, Node cmp, Node val) {
        // 使用Unsafe进行CAS操作
        return UNSAFE.compareAndSwapObject(a, ((long)i << ASHIFT) + ABASE, cmp, val);
    }

    /**
     * 尝试与对方节点进行匹配
     * @param slot 槽位中的节点
     * @param node 当前节点
     * @return 如果匹配成功返回true,否则返回false
     */
    private boolean tryMatch(Node slot, Node node) {
        // 设置匹配关系
        node.match = slot;
        // CAS操作更新槽位
        if (compareAndSetSlot(arena, hashIndex(), slot, node)) {
            // 唤醒等待的线程
            LockSupport.unpark(slot.waiter);
            return true;
        }
        return false;
    }

    /**
     * 等待匹配
     * 当前线程进入等待状态直到被匹配
     * @param node 当前节点
     * @param timed 是否使用超时
     * @param nanos 超时时间(纳秒)
     * @return 交换结果
     */
    private Object awaitMatch(Node node, boolean timed, long nanos) {
        // 设置等待线程
        node.waiter = Thread.currentThread();
        // 开始等待
        Object x = node.item;
        
        // 计算超时时间
        long lastTime = timed ? System.nanoTime() : 0L;
        
        // 无限循环等待匹配
        while (x == node.item) {
            // 检查线程是否被中断
            if (Thread.interrupted()) {
                // 取消等待
                cancelWait(node);
                return node;
            }
            
            // 检查是否超时
            if (timed) {
                long now = System.nanoTime();
                nanos -= now - lastTime;
                lastTime = now;
                if (nanos <= 0) {
                    // 超时,取消等待
                    cancelWait(node);
                    return TIMED_OUT;
                }
                // 阻塞等待指定时间
                LockSupport.parkNanos(this, nanos);
            } else {
                // 无限期阻塞等待
                LockSupport.park(this);
            }
            
            // 检查匹配结果
            if (node.match != null) {
                // 匹配成功,获取数据
                x = node.data;
            }
        }
        
        return x;
    }

    /**
     * 取消等待
     * 当线程被中断或超时时调用
     * @param node 要取消等待的节点
     */
    private void cancelWait(Node node) {
        // 从槽位中移除节点
        Node[] a = arena;
        if (a != null) {
            int index = hashIndex();
            Node slot = a[index];
            if (slot == node) {
                compareAndSetSlot(a, index, slot, null);
            }
        }
        // 唤醒可能等待的线程
        LockSupport.unpark(node.waiter);
    }

    /**
     * 减少自旋次数
     * @param spins 当前自旋次数
     * @return 减少后的自旋次数
     */
    private int decrementSpins(int spins) {
        return (spins & SPINS) == 0 ? 0 : spins - 1;
    }

    /**
     * 自旋次数常量
     */
    private static final int SPINS = (1 << 8) - 1;

    /**
     * 等待线程
     */
    volatile Thread waiter;

5. Unsafe相关字段和方法(详细注释)

    /**
     * Unsafe类实例
     * 提供底层的原子操作
     */
    private static final sun.misc.Unsafe UNSAFE = getUnsafe();

    /**
     * 数组基地址
     */
    private static final long ABASE;

    /**
     * 获取Unsafe实例
     * @return Unsafe实例
     */
    private static sun.misc.Unsafe getUnsafe() {
        try {
            return sun.misc.Unsafe.getUnsafe();
        } catch (SecurityException se) {
            try {
                return java.security.AccessController.doPrivileged
                    (new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
                        public sun.misc.Unsafe run() throws Exception {
                            Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
                            for (java.lang.reflect.Field f : k.getDeclaredFields()) {
                                f.setAccessible(true);
                                Object x = f.get(null);
                                if (k.isInstance(x))
                                    return k.cast(x);
                            }
                            throw new NoSuchFieldError("the Unsafe");
                        }});
            } catch (java.security.PrivilegedActionException e) {
                throw new RuntimeException("Could not initialize intrinsics",
                                           e.getCause());
            }
        }
    }

    /**
     * 静态初始化块
     */
    static {
        try {
            ABASE = UNSAFE.arrayBaseOffset(Node[].class);
            int scale = UNSAFE.arrayIndexScale(Node[].class);
            if ((scale & (scale - 1)) != 0)
                throw new Error("data type scale not a power of two");
            // 省略具体的初始化代码
        } catch (Exception e) {
            throw new Error(e);
        }
    }

6. Exchanger 的特点分析

核心设计理念:

/**
 * Exchanger的核心设计思想:
 * 
 * 1. 对称数据交换:
 *    - 两个线程通过Exchanger交换数据
 *    - 提供原子性的数据交换操作
 *    - 支持阻塞和超时等待
 *    - 保证交换的原子性和一致性
 * 
 * 2. 多槽位机制:
 *    - 使用多个槽位减少线程竞争
 *    - 通过哈希分布将线程分散到不同槽位
 *    - 提高并发性能和吞吐量
 *    - 优化内存访问局部性
 * 
 * 3. 无锁设计:
 *    - 使用CAS操作实现无锁化
 *    - 减少传统锁的开销和阻塞
 *    - 提供乐观锁机制
 *    - 支持高并发环境
 * 
 * 4. 线程本地存储:
 *    - 每个线程维护自己的Node节点
 *    - 减少对象创建和垃圾回收开销
 *    - 优化内存使用
 *    - 提高性能
 * 
 * 5. 灵活的等待机制:
 *    - 支持无限期等待
 *    - 支持可中断等待
 *    - 支持超时等待
 *    - 提供多种等待选项
 * 
 * 6. 高效的交换算法:
 *    - 快速匹配机制
 *    - 优化的内存布局
 *    - 高效的线程调度
 *    - 及时的垃圾回收
 * 
 * 7. 内存优化:
 *    - 及时清理不用的节点
 *    - 重用Node对象
 *    - 避免内存泄漏
 *    - 优化GC性能
 * 
 * 适用场景:
 * - 生产者-消费者模式的数据交换
 * - 线程间的数据传递
 * - 实现管道或通道
 * - 需要原子性数据交换的场景
 * - 高并发环境下的数据交换
 * - 需要双向数据交换的场景
 */

性能特征分析:

/**
 * Exchanger的性能特征:
 * 
 * 时间复杂度:
 * - exchange(x): O(1) 平均情况,O(∞) 最坏情况(等待时间)
 * - exchange(x, timeout, unit): O(1) 平均情况,O(∞) 最坏情况(等待时间)
 * 
 * 空间复杂度:
 * - O(n) 等待队列空间(n为等待线程数)
 * - O(m) 槽位数组空间(m为槽数组大小)
 * - 每个实例固定开销较小
 * 
 * 并发特性:
 * - 完全线程安全
 * - 支持高并发读写
 * - 无死锁风险
 * - 支持可重入性
 * 
 * 多槽位优势:
 * - 减少线程竞争:多个槽位分散线程
 * - 提高吞吐量:并行处理多个交换
 * - 优化性能:减少CAS竞争
 * - 支持扩展:动态调整槽数量
 * 
 * 与SynchronousQueue对比:
 * - Exchanger: 双向数据交换,两个线程交换数据
 * - SynchronousQueue: 单向数据传递,生产者传递给消费者
 * - Exchanger: 支持超时和中断
 * - SynchronousQueue: 更简单的传递语义
 * 
 * 内存使用:
 *    - 每个实例固定开销较小
 *    - 等待线程会增加内存使用
 *    - 及时GC,避免内存泄漏
 *    - 线程本地存储优化内存使用
 * 
 * 适用性:
 *    - 双向数据交换:性能优异
 *    - 简单数据传递:可能不如SynchronousQueue
 *    - 高并发交换:性能优异
 *    - 需要超时控制:支持完善
 *    - 需要中断支持:支持完善
 * 
 * 性能优化:
 *    - 合理设置槽数量
 *    - 避免不必要的等待
 *    - 使用超时机制避免无限等待
 *    - 正确处理中断异常
 *    - 监控等待线程数量
 *    - 优化自旋次数
 */

7. 使用示例和最佳实践

/**
 * 使用示例:
 * 
 * // 基本使用:生产者-消费者数据交换
 * Exchanger<String> exchanger = new Exchanger<>();
 * 
 * // 生产者线程
 * Thread producer = new Thread(() -> {
 *     try {
 *         String dataToSend = "Hello from producer";
 *         System.out.println("Producer sending: " + dataToSend);
 *         String receivedData = exchanger.exchange(dataToSend);
 *         System.out.println("Producer received: " + receivedData);
 *     } catch (InterruptedException e) {
 *         Thread.currentThread().interrupt();
 *     }
 * });
 * 
 * // 消费者线程
 * Thread consumer = new Thread(() -> {
 *     try {
 *         String dataToSend = "Hello from consumer";
 *         System.out.println("Consumer sending: " + dataToSend);
 *         String receivedData = exchanger.exchange(dataToSend);
 *         System.out.println("Consumer received: " + receivedData);
 *     } catch (InterruptedException e) {
 *         Thread.currentThread().interrupt();
 *     }
 * });
 * 
 * producer.start();
 * consumer.start();
 * 
 * // 带超时的数据交换示例
 * Exchanger<Integer> timeoutExchanger = new Exchanger<>();
 * 
 * Thread sender = new Thread(() -> {
 *     try {
 *         Integer data = 42;
 *         System.out.println("Sender exchanging: " + data);
 *         Integer received = timeoutExchanger.exchange(data, 5, TimeUnit.SECONDS);
 *         System.out.println("Sender received: " + received);
 *     } catch (InterruptedException e) {
 *         Thread.currentThread().interrupt();
 *     } catch (TimeoutException e) {
 *         System.out.println("Sender timed out");
 *     }
 * });
 * 
 * Thread receiver = new Thread(() -> {
 *     try {
 *         Thread.sleep(3000); // 模拟延迟
 *         Integer data = 100;
 *         System.out.println("Receiver exchanging: " + data);
 *         Integer received = timeoutExchanger.exchange(data, 5, TimeUnit.SECONDS);
 *         System.out.println("Receiver received: " + received);
 *     } catch (InterruptedException e) {
 *         Thread.currentThread().interrupt();
 *     } catch (TimeoutException e) {
 *         System.out.println("Receiver timed out");
 *     }
 * });
 * 
 * sender.start();
 * receiver.start();
 * 
 * // 多对数据交换示例
 * class DataExchangePipeline {
 *     private final Exchanger<String> exchanger1 = new Exchanger<>();
 *     private final Exchanger<String> exchanger2 = new Exchanger<>();
 *     
 *     public void startPipeline() {
 *         // 第一阶段线程
 *         Thread stage1 = new Thread(() -> {
 *             try {
 *                 String input = "Input data";
 *                 String processed = "Processed: " + input;
 *                 System.out.println("Stage 1: " + processed);
 *                 String result = exchanger1.exchange(processed);
 *                 System.out.println("Stage 1 received: " + result);
 *             } catch (InterruptedException e) {
 *                 Thread.currentThread().interrupt();
 *             }
 *         });
 *         
 *         // 第二阶段线程
 *         Thread stage2 = new Thread(() -> {
 *             try {
 *                 String input = "Stage 2 data";
 *                 System.out.println("Stage 2: " + input);
 *                 String result1 = exchanger1.exchange(input);
 *                 System.out.println("Stage 2 received from Stage 1: " + result1);
 *                 
 *                 String processed = "Final: " + result1 + " + " + input;
 *                 String result2 = exchanger2.exchange(processed);
 *                 System.out.println("Stage 2 received final: " + result2);
 *             } catch (InterruptedException e) {
 *                 Thread.currentThread().interrupt();
 *             }
 *         });
 *         
 *         // 第三阶段线程
 *         Thread stage3 = new Thread(() -> {
 *             try {
 *                 String input = "Output data";
 *                 System.out.println("Stage 3: " + input);
 *                 String result = exchanger2.exchange(input);
 *                 System.out.println("Stage 3 received: " + result);
 *             } catch (InterruptedException e) {
 *                 Thread.currentThread().interrupt();
 *             }
 *         });
 *         
 *         stage1.start();
 *         stage2.start();
 *         stage3.start();
 *     }
 * }
 * 
 * // 缓冲区交换示例
 * class BufferExchanger {
 *     private final Exchanger<List<String>> exchanger = new Exchanger<>();
 *     private final List<String> fillBuffer = new ArrayList<>();
 *     private final List<String> emptyBuffer = new ArrayList<>();
 *     
 *     public void startProducer() {
 *         Thread producer = new Thread(() -> {
 *             try {
 *                 for (int i = 0; i < 100; i++) {
 *                     fillBuffer.add("Item " + i);
 *                     if (fillBuffer.size() >= 10) {
 *                         System.out.println("Producer exchanging full buffer");
 *                         List<String> exchanged = exchanger.exchange(fillBuffer);
 *                         fillBuffer.clear();
 *                         // 使用交换回来的空缓冲区
 *                         emptyBuffer.addAll(exchanged);
 *                     }
 *                 }
 *                 // 发送最后一个缓冲区
 *                 if (!fillBuffer.isEmpty()) {
 *                     List<String> exchanged = exchanger.exchange(fillBuffer);
 *                     fillBuffer.clear();
 *                 }
 *             } catch (InterruptedException e) {
 *                 Thread.currentThread().interrupt();
 *             }
 *         });
 *         producer.start();
 *     }
 *     
 *     public void startConsumer() {
 *         Thread consumer = new Thread(() -> {
 *             try {
 *                 while (true) {
 *                     System.out.println("Consumer exchanging empty buffer");
 *                     List<String> exchanged = exchanger.exchange(emptyBuffer);
 *                     // 处理接收到的填充缓冲区
 *                     for (String item : exchanged) {
 *                         System.out.println("Processing: " + item);
 *                     }
 *                     exchanged.clear();
 *                     // 使用交换回来的空缓冲区
 *                     emptyBuffer.addAll(exchanged);
 *                 }
 *             } catch (InterruptedException e) {
 *                 Thread.currentThread().interrupt();
 *             }
 *         });
 *         consumer.start();
 *     }
 * }
 * 
 * 最佳实践:
 * 
 * 1. 正确处理中断异常:
 *    Exchanger<String> exchanger = new Exchanger<>();
 *    
 *    // 正确的做法:处理中断异常
 *    try {
 *        String data = "Hello";
 *        String received = exchanger.exchange(data);
 *        System.out.println("Received: " + received);
 *    } catch (InterruptedException e) {
 *        Thread.currentThread().interrupt(); // 恢复中断状态
 *        System.out.println("Exchange interrupted");
 *    }
 *    
 *    // 错误的做法:忽略中断异常
 *    // String received = exchanger.exchange("Hello"); // 没有处理异常
 * 
 * 2. 合理使用超时机制:
 *    Exchanger<String> exchanger = new Exchanger<>();
 *    
 *    // 使用超时避免无限等待
 *    try {
 *        String data = "Hello";
 *        String received = exchanger.exchange(data, 5, TimeUnit.SECONDS);
 *        System.out.println("Received: " + received);
 *    } catch (InterruptedException e) {
 *        Thread.currentThread().interrupt();
 *        System.out.println("Exchange interrupted");
 *    } catch (TimeoutException e) {
 *        System.out.println("Exchange timed out");
 *        // 处理超时情况
 *    }
 * 
 * 3. 避免死锁:
 *    Exchanger<String> exchanger1 = new Exchanger<>();
 *    Exchanger<String> exchanger2 = new Exchanger<>();
 *    
 *    // 错误的做法:可能导致死锁
 *    // Thread t1 = new Thread(() -> {
 *    //     try {
 *    //         String data1 = exchanger1.exchange("data1");
 *    //         String data2 = exchanger2.exchange("data2"); // 可能与另一个线程形成死锁
 *    //     } catch (InterruptedException e) {
 *    //         Thread.currentThread().interrupt();
 *    //     }
 *    // });
 *    // 
 *    // Thread t2 = new Thread(() -> {
 *    //     try {
 *    //         String data2 = exchanger2.exchange("data2"); // 可能与另一个线程形成死锁
 *    //         String data1 = exchanger1.exchange("data1");
 *    //     } catch (InterruptedException e) {
 *    //         Thread.currentThread().interrupt();
 *    //     }
 *    // });
 *    
 *    // 正确的做法:保持一致的交换顺序
 *    Thread t1 = new Thread(() -> {
 *        try {
 *            String data1 = exchanger1.exchange("data1");
 *            String data2 = exchanger1.exchange("data2"); // 保持相同的交换顺序
 *        } catch (InterruptedException e) {
 *            Thread.currentThread().interrupt();
 *        }
 *    });
 *    
 *    Thread t2 = new Thread(() -> {
 *        try {
 *            String data1 = exchanger1.exchange("data1"); // 保持相同的交换顺序
 *            String data2 = exchanger1.exchange("data2");
 *        } catch (InterruptedException e) {
 *            Thread.currentThread().interrupt();
 *        }
 *    });
 * 
 * 4. 正确处理数据类型:
 *    Exchanger<List<String>> exchanger = new Exchanger<>();
 *    
 *    // 使用不可变数据避免副作用
 *    List<String> data = Collections.unmodifiableList(Arrays.asList("item1", "item2"));
 *    try {
 *        List<String> received = exchanger.exchange(data);
 *        System.out.println("Received: " + received);
 *    } catch (InterruptedException e) {
 *        Thread.currentThread().interrupt();
 *    }
 *    
 *    // 或者使用防御性复制
 *    List<String> mutableData = new ArrayList<>(Arrays.asList("item1", "item2"));
 *    List<String> immutableData = new ArrayList<>(mutableData);
 *    try {
 *        List<String> received = exchanger.exchange(immutableData);
 *        System.out.println("Received: " + received);
 *    } catch (InterruptedException e) {
 *        Thread.currentThread().interrupt();
 *    }
 * 
 * 5. 合理设置超时时间:
 *    Exchanger<String> exchanger = new Exchanger<>();
 *    
 *    // 根据业务需求设置合理的超时时间
 *    long timeout = calculateAppropriateTimeout(); // 根据实际情况计算
 *    try {
 *        String data = "Hello";
 *        String received = exchanger.exchange(data, timeout, TimeUnit.MILLISECONDS);
 *        System.out.println("Received: " + received);
 *    } catch (InterruptedException e) {
 *        Thread.currentThread().interrupt();
 *    } catch (TimeoutException e) {
 *        System.out.println("Exchange timed out after " + timeout + " ms");
 *        // 处理超时情况
 *    }
 *    
 *    private long calculateAppropriateTimeout() {
 *        // 根据业务逻辑和系统性能计算合适的超时时间
 *        return 10000; // 10秒
 *    }
 * 
 * 6. 监控和调试:
 *    Exchanger<String> exchanger = new Exchanger<>();
 *    
 *    // 在生产环境中添加监控
 *    public String monitoredExchange(String data) throws InterruptedException {
 *        long startTime = System.nanoTime();
 *        try {
 *            String received = exchanger.exchange(data);
 *            long endTime = System.nanoTime();
 *            long duration = endTime - startTime;
 *            System.out.println("Exchange completed in " + duration + " ns");
 *            return received;
 *        } catch (InterruptedException e) {
 *            long endTime = System.nanoTime();
 *            long duration = endTime - startTime;
 *            System.out.println("Exchange interrupted after " + duration + " ns");
 *            throw e;
 *        }
 *    }
 * 
 * 7. 异常处理:
 *    Exchanger<String> exchanger = new Exchanger<>();
 *    
 *    // 全面的异常处理
 *    public void robustExchange(String data) {
 *        try {
 *            String received = exchanger.exchange(data);
 *            processReceivedData(received);
 *        } catch (InterruptedException e) {
 *            Thread.currentThread().interrupt();
 *            handleInterruption();
 *        } catch (Exception e) {
 *            handleError(e);
 *        }
 *    }
 *    
 *    private void processReceivedData(String data) {
 *        // 处理接收到的数据
 *        System.out.println("Processing: " + data);
 *    }
 *    
 *    private void handleInterruption() {
 *        System.out.println("Exchange was interrupted");
 *        // 执行清理操作
 *        cleanupResources();
 *    }
 *    
 *    private void handleError(Exception e) {
 *        System.err.println("Error during exchange: " + e.getMessage());
 *        // 记录日志或执行其他错误处理
 *        logError(e);
 *    }
 *    
 *    private void cleanupResources() {
 *        // 清理资源
 *        System.out.println("Cleaning up resources");
 *    }
 *    
 *    private void logError(Exception e) {
 *        // 记录错误日志
 *        System.err.println("Error logged: " + e.getMessage());
 *    }
 * 
 * 8. 性能调优:
 *    // 在高并发场景下优化性能
 *    Exchanger<String> exchanger = new Exchanger<>();
 *    
 *    // 使用线程池管理线程
 *    ExecutorService executor = Executors.newFixedThreadPool(10);
 *    
 *    // 批量提交任务
 *    for (int i = 0; i < 100; i++) {
 *        final int taskId = i;
 *        executor.submit(() -> {
 *            try {
 *                String data = "Task " + taskId + " data";
 *                String received = exchanger.exchange(data);
 *                System.out.println("Task " + taskId + " received: " + received);
 *            } catch (InterruptedException e) {
 *                Thread.currentThread().interrupt();
 *            }
 *        });
 *    }
 *    
 *    // 优雅关闭
 *    executor.shutdown();
 *    try {
 *        if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
 *            executor.shutdownNow();
 *        }
 *    } catch (InterruptedException e) {
 *        executor.shutdownNow();
 *        Thread.currentThread().interrupt();
 *    }
 * 
 * 9. 资源管理:
 *    class ManagedExchanger<T> {
 *        private final Exchanger<T> exchanger = new Exchanger<>();
 *        private final AtomicBoolean closed = new AtomicBoolean(false);
 *        
 *        public T exchange(T data) throws InterruptedException {
 *            if (closed.get()) {
 *                throw new IllegalStateException("Exchanger is closed");
 *            }
 *            return exchanger.exchange(data);
 *        }
 *        
 *        public T exchange(T data, long timeout, TimeUnit unit) 
 *                throws InterruptedException, TimeoutException {
 *            if (closed.get()) {
 *                throw new IllegalStateException("Exchanger is closed");
 *            }
 *            return exchanger.exchange(data, timeout, unit);
 *        }
 *        
 *        public void close() {
 *            if (closed.compareAndSet(false, true)) {
 *                System.out.println("Exchanger closed");
 *                // 执行清理操作
 *            }
 *        }
 *    }
 * 
 * 10. 测试和验证:
 *    // 编写测试用例验证Exchanger的正确性
 *    class ExchangerTest {
 *        @Test
 *        public void testBasicExchange() throws InterruptedException {
 *            Exchanger<String> exchanger = new Exchanger<>();
 *            CountDownLatch latch = new CountDownLatch(2);
 *            AtomicReference<String> result1 = new AtomicReference<>();
 *            AtomicReference<String> result2 = new AtomicReference<>();
 *            
 *            Thread t1 = new Thread(() -> {
 *                try {
 *                    String received = exchanger.exchange("from-t1");
 *                    result1.set(received);
 *                    latch.countDown();
 *                } catch (InterruptedException e) {
 *                    Thread.currentThread().interrupt();
 *                }
 *            });
 *            
 *            Thread t2 = new Thread(() -> {
 *                try {
 *                    String received = exchanger.exchange("from-t2");
 *                    result2.set(received);
 *                    latch.countDown();
 *                } catch (InterruptedException e) {
 *                    Thread.currentThread().interrupt();
 *                }
 *            });
 *            
 *            t1.start();
 *            t2.start();
 *            
 *            latch.await(5, TimeUnit.SECONDS);
 *            
 *            assertEquals("from-t2", result1.get());
 *            assertEquals("from-t1", result2.get());
 *        }
 *    }
 */

8. 与其他同步机制的比较

/**
 * Exchanger vs SynchronousQueue vs BlockingQueue vs CountDownLatch:
 * 
 * Exchanger:
 * - 双向数据交换
 * - 两个线程交换数据
 * - 支持超时和中断
 * - 原子性数据交换
 * - 适用于需要双向通信的场景
 * 
 * SynchronousQueue:
 * - 单向数据传递
 * - 生产者传递给消费者
 * - 不存储元素
 * - 最低延迟,最高吞吐量
 * - 适用于直接传递的场景
 * 
 * BlockingQueue:
 * - 单向数据存储和传递
 * - 支持多个生产者和消费者
 * - 可以存储多个元素
 * - 支持有界和无界队列
 * - 适用于缓冲和排队的场景
 * 
 * CountDownLatch:
 * - 计数器机制
 * - 一个或多个线程等待其他线程完成
 * - 一次性使用
 * - 不支持数据交换
 * - 适用于协调多个线程的场景
 * 
 * 性能对比:
 * - 简单传递:SynchronousQueue > Exchanger > BlockingQueue > CountDownLatch
 * - 双向交换:Exchanger > SynchronousQueue > BlockingQueue > CountDownLatch
 * - 多线程协调:CountDownLatch > BlockingQueue > Exchanger > SynchronousQueue
 * - 数据缓冲:BlockingQueue > Exchanger > SynchronousQueue > CountDownLatch
 * - 内存使用:SynchronousQueue < Exchanger < BlockingQueue < CountDownLatch
 * 
 * 选择建议:
 * - 双向数据交换:Exchanger
 * - 直接传递:SynchronousQueue
 * - 数据缓冲:BlockingQueue
 * - 线程协调:CountDownLatch
 * - 读写分离:ReentrantReadWriteLock
 * - 复杂同步:ReentrantLock
 * 
 * 使用场景:
 * - Exchanger:生产者-消费者数据交换、管道实现、双向通信
 * - SynchronousQueue:直接传递、线程池任务传递
 * - BlockingQueue:缓冲区、任务队列、消息传递
 * - CountDownLatch:主线程等待子线程完成、启动门闩、关闭门闩
 * 
 * 线程安全性:
 * - 所有机制都提供完全的线程安全性
 * - Exchanger和SynchronousQueue支持高并发
 * - BlockingQueue支持生产者消费者模式
 * - CountDownLatch支持协调同步
 * 
 * 功能丰富度:
 * - Exchanger:支持超时、中断、双向交换
 * - SynchronousQueue:简单直接传递
 * - BlockingQueue:丰富的队列操作
 * - CountDownLatch:简单的计数器操作
 */

9. 总结

ReentrantReadWriteLock 的核心特性:

  1. 读写分离

    • 读锁:共享锁,多个读线程可以同时持有
    • 写锁:独占锁,写线程独占访问
    • 读读不互斥,读写互斥,写写互斥
  2. 可重入性

    • 支持读锁和写锁的可重入
    • 每个线程维护自己的持有计数
    • 完全释放时才允许其他线程获取
  3. 锁降级

    • 支持写锁降级为读锁
    • 先获取写锁,再获取读锁,最后释放写锁
    • 保证数据的一致性
  4. 公平性选择

    • 提供公平和非公平两种模式
    • 公平锁避免线程饥饿
    • 非公平锁提高性能
  5. 线程本地存储

    • 使用ThreadLocal跟踪每个线程的读锁持有情况
    • 避免竞争和同步开销
    • 优化单个读线程的场景
  6. AQS集成

    • 继承AbstractQueuedSynchronizer
    • 复用成熟的队列管理机制
    • 提供完整的同步框架
  7. Condition支持

    • 写锁支持Condition
    • 提供灵活的线程等待/通知机制
    • 不支持读锁的Condition
  8. 丰富的查询API

    • 提供详细的锁状态查询
    • 支持监控和诊断
    • 便于调试和性能调优

适用场景:

  • 读操作远多于写操作的场景
  • 需要高并发读取的场景
  • 需要比ReentrantLock更细粒度控制的场景
  • 需要Condition支持的写锁场景
  • 缓存系统、数据库访问等读多写少的应用

注意事项:

  • 必须在finally块中释放锁
  • 避免读写锁嵌套导致死锁
  • 合理选择公平性策略
  • 正确处理中断异常
  • 监控锁的使用情况
  • 避免长时间持有锁
  • 注意读写锁的语义区别

性能优化建议:

  1. 根据读写比例选择合适的锁类型
  2. 合理设置超时时间
  3. 使用公平锁避免线程饥饿
  4. 监控锁的竞争情况
  5. 优化临界区代码减少持有时间
  6. 考虑使用更细粒度的锁
  7. 定期分析和调优锁的使用
  8. 在读多写少的场景下充分发挥读并发优势
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值