crossbeam 是一个并发包, 还是挺好用的。

crossbeam = "0.8.1"
  • AtomicCell: 线程安全的可变容器。
  • crossbeam-channel: 多生产者多消费者通道。
  • crossbeam-deque: 工作窃取双端队列。
  • crossbeam-queue: 无锁队列(SegQueue 和 ArrayQueue)。
  • crossbeam-skiplist: 并发跳表。
  • crossbeam-epoch: 基于世代的内存回收机制。

有界通道(Bounded Channel):

use crossbeam::channel::bounded;

fn main() {
    let (sender, receiver) = bounded(2);
    sender.send("111").unwrap();
    sender.send("222").unwrap();
    // if sender.try_send("Hello").is_err() {
    //     println!("Buffer is full, unable to send");
    // }
    std::thread::spawn(move || {
        sender.send("333");

    });

    // std::thread::sleep(std::time::Duration::from_secs(1));


    let msg1=receiver.recv().unwrap();
    let msg2=receiver.recv().unwrap();
    println!("Received: {}", msg1);  // Received: Hello 1
    println!("Received: {}", msg2);  // Received: Hello 2

    // 这时,第三条消息还在发送,因为缓冲区是满的
    let msg3 = receiver.recv().unwrap();
    println!("Received: {}", msg3);  // Received: Hello 3
    // 超时尝试接收消息
    //if let Ok(msg) = receiver.recv_timeout(Duration::from_secs(1)) {
    //    println!("Received: {}", msg);
    //} else {
    //    println!("No message arrived within 1 second");
    //}

}

无界通道

fn main() {
    let (sender, receiver) = unbounded();

    // 发送消息
    sender.send("Hello from the thread").unwrap();

    // 接收消息
    let msg = receiver.recv().unwrap();
    println!("{}", msg);  // Hello from the thread
}

AtomicCell 只能存储实现了 Copy trait 的数据类型,因此我们不能直接使用 AtomicCell 来存储和管理 Worker 或其他复杂类型的数据。这一点在多线程编程中尤为重要,因为使用像 Worker 这样复杂的数据结构时,必须使用智能指针和同步原语(如 Arc 和 Mutex)来确保数据的安全访问。

use crossbeam::atomic::AtomicCell;

fn main() {
    let atomic_value = AtomicCell::new(42);
    
    // 在多个线程中安全地读写值
    atomic_value.store(43);
    println!("Value: {}", atomic_value.load()); // Value: 43
}

crossbeam-deque 是一个工作窃取(work-stealing)双端队列库,适用于任务调度和并行任务执行。它提供了一种灵活的机制来创建工作者线程,它们可以从自己的任务队列中获取任务,也可以从其他工作者的任务队列中窃取任务,以确保负载均衡。

crossbeam-deque 中主要包括以下几个结构:
Injector:全局任务注入器,用于将任务推入队列,以便工作者线程可以窃取任务执行。
Worker:创建两个工作者队列,每个工作者都能从自己的队列中获取任务。
Stealer:为每个工作者创建一个窃取者,允许一个工作者从另一个工作者的队列中窃取任务。

use crossbeam_deque::{Injector, Steal, Worker};
use std::sync::{Arc, Mutex};
use std::thread;
use crossbeam::atomic::AtomicCell;

fn main() {
    // 创建一个全局任务注入器
    let injector = Arc::new(Injector::new());

    // 使用 Arc 和 Mutex 创建两个工作者
    let worker1 = Arc::new(Mutex::new(Worker::<i32>::new_fifo()));
    let worker2 = Arc::new(Mutex::new(Worker::<i32>::new_fifo()));

    let stealer1 = worker1.lock().unwrap().stealer();
    let stealer2 = worker2.lock().unwrap().stealer();

    // 向注入器中推入一些任务
    for i in 0..5 {
        injector.push(i);
    }

    // 工作者线程
    let worker1_clone = Arc::clone(&worker1);
    let handle1 = thread::spawn(move || {
        loop {
            let mut worker1 = worker1_clone.lock().unwrap();
            if let Some(task) = worker1.pop() {
                println!("Worker 1 executing task: {}", task);
            } else {
                break;
            }
        }
    });

    // 另一个工作者线程
    let worker2_clone = Arc::clone(&worker2);
    let handle2 = thread::spawn(move || {
        loop {
            let mut worker2 = worker2_clone.lock().unwrap();
            if let Some(task) = worker2.pop() {
                println!("Worker 2 executing task: {}", task);
            } else {
                match stealer1.steal() {
                    Steal::Success(task) => println!("Worker 2 stole task from Worker 1: {}", task),
                    Steal::Empty => break,
                    Steal::Retry => continue,
                }
            }
        }
    });

    // 窃取者线程
    let injector_clone = Arc::clone(&injector);
    let worker1_clone2 = Arc::clone(&worker1);
    let handle3 = thread::spawn(move || {
        loop {
            match injector_clone.steal_batch_and_pop(&worker1_clone2.lock().unwrap()) {
                Steal::Success(task) => println!("Worker 1 executing stolen task from injector: {}", task),
                Steal::Empty => break,
                Steal::Retry => continue,
            }
        }
    });

    handle1.join().unwrap();
    handle2.join().unwrap();
    handle3.join().unwrap();
}

SegQueue 是一个无锁 (lock-free) 的多生产者多消费者队列。它是非阻塞 (non-blocking) 的,这意味着它在操作时不会使用传统的锁 (Mutex 或类似机制) 来控制并发访问。这种设计使得 SegQueue 能够在高度并发的环境中表现出色。

use crossbeam_queue::SegQueue;
use std::sync::Arc;
use std::thread;

fn main() {
    let queue = Arc::new(SegQueue::new());

    // 创建生产者线程,向队列中推入数据
    let producers: Vec<_> = (0..4).map(|i| {
        let queue = Arc::clone(&queue);
        thread::spawn(move || {
            for j in 0..10 {
                queue.push(i * 10 + j);
                println!("Producer {} pushed {}", i, i * 10 + j);
            }
        })
    }).collect();

    // 等待所有生产者完成
    for producer in producers {
        producer.join().unwrap();
    }

    // 创建消费者线程,从队列中弹出数据
    let consumers: Vec<_> = (0..4).map(|i| {
        let queue = Arc::clone(&queue);
        thread::spawn(move || {
            loop {
                match queue.pop() {
                    Some(value) => {
                        println!("Consumer {} popped {}", i, value);
                    },
                    None => {
                        // 如果队列为空,跳出循环
                        break;
                    }
                }
            }
        })
    }).collect();

    // 等待所有消费者完成
    for consumer in consumers {
        consumer.join().unwrap();
    }
}

crossbeam-skiplist 是一个用于并发环境的高效数据结构,支持快速的插入、删除和查找操作。跳表是一种有序的链表结构,它通过多级索引实现高效的搜索、插入和删除操作。crossbeam-skiplist 提供了一个线程安全的跳表实现,可以在高并发环境中使用。

use crossbeam_skiplist::SkipMap;
use std::sync::Arc;
use std::thread;

fn main() {
    // 创建一个 SkipMap 实例
    let map = Arc::new(SkipMap::new());

    // 创建多个写入线程
    let writers: Vec<_> = (0..4).map(|i| {
        let map = Arc::clone(&map);
        thread::spawn(move || {
            for j in 0..10 {
                map.insert(i * 10 + j, format!("value {}", i * 10 + j));
                println!("Writer thread {} inserted key {}", i, i * 10 + j);
            }
        })
    }).collect();

    // 等待所有写入线程完成
    for writer in writers {
        writer.join().unwrap();
    }

    // 创建多个读取线程
    let readers: Vec<_> = (0..4).map(|i| {
        let map = Arc::clone(&map);
        thread::spawn(move || {
            for j in 0..10 {
                let key = i * 10 + j;
                if let Some(entry) = map.get(&key) {
                    println!("Reader thread {} found key {}: {}", i, key, entry.value());
                } else {
                    println!("Reader thread {} did not find key {}", i, key);
                }
            }
        })
    }).collect();

    // 等待所有读取线程完成
    for reader in readers {
        reader.join().unwrap();
    }

    // 删除部分数据
    for key in 0..10 {
        map.remove(&key);
        println!("Removed key {}", key);
    }

    // 检查是否成功删除
    for key in 0..10 {
        if let Some(entry) = map.get(&key) {
            println!("Key {} still exists: {}", key, entry.value());
        } else {
            println!("Key {} has been removed", key);
        }
    }
}


putao
5 声望0 粉丝

推动世界向前发展,改善民生。