• Rust有没有信号量机制,在缓存有数据的时候才允许等待的进程取数据?


    Rust提供了信号量(Semaphore)机制,尽管它并没有直接提供类似于某些其他编程语言中的Semaphore类。然而,你可以使用std::sync::Mutex和std::sync::Condvar(条件变量)组合来实现信号量的功能。

    信号量通常用于控制对共享资源的访问,通过维护一个计数器来限制同时访问资源的线程数。当资源可用时(即缓存中有数据时),等待的线程可以被唤醒并获取资源。

    在Rust中,你可以使用Mutex来保护共享资源并提供互斥访问,同时使用Condvar来让等待的线程在条件满足时被唤醒。下面是一个简单的示例,展示了如何使用Mutex和Condvar来实现一个信号量,该信号量允许在缓存有数据时唤醒等待的线程:

    use std::sync::{Mutex, Condvar, Arc};  
    use std::thread;  
    use std::time::Duration;  
      
    // 缓存结构  
    struct Cache {  
        data: Mutex<Vec<i32>>,  // 互斥锁保护的数据  
        not_empty: Condvar,     // 条件变量,用于等待数据可用  
        not_full: Condvar,      // 条件变量,用于等待空间可用(如果需要的话)  
    }  
      
    impl Cache {  
        fn new(capacity: usize) -> Cache {  
            Cache {  
                data: Mutex::new(Vec::with_capacity(capacity)),  
                not_empty: Condvar::new(),  
                not_full: Condvar::new(),  
            }  
        }  
      
        // 尝试从缓存中取出数据  
        fn try_pop(&self) -> Option<i32> {  
            let mut data = self.data.lock().unwrap();  
            if data.is_empty() {  
                None  
            } else {  
                Some(data.remove(0))  
            }  
        }  
      
        // 向缓存中添加数据  
        fn push(&self, value: i32) {  
            let mut data = self.data.lock().unwrap();  
            data.push(value);  
            self.not_empty.notify_one(); // 通知可能等待的消费者线程  
        }  
      
        // 从缓存中获取数据,如果没有数据则阻塞  
        fn pop(&self) -> i32 {  
            let mut data = self.data.lock().unwrap();  
            while data.is_empty() {  
                // 等待直到有数据可用或超时  
                self.not_empty.wait(data.as_mut()).unwrap();  
            }  
            data.remove(0)  
        }  
    }  
      
    fn main() {  
        let cache = Arc::new(Cache::new(10)); // 假设缓存容量为10  
      
        // 生产者线程  
        let producer = thread::spawn(move || {  
            for i in 1..=5 {  
                thread::sleep(Duration::from_secs(1));  
                cache.push(i);  
                println!("Produced: {}", i);  
            }  
        });  
      
        // 消费者线程  
        let consumer = thread::spawn(move || {  
            for _ in 1..=5 {  
                let value = cache.pop();  
                println!("Consumed: {}", value);  
            }  
        });  
      
        // 等待生产者和消费者线程完成  
        producer.join().unwrap();  
        consumer.join().unwrap();  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

    在这个示例中,Cache结构体有一个互斥锁data来保护对Vec的访问,以及两个条件变量not_empty和not_full(尽管在这个例子中我们并没有使用not_full,因为我们没有实现缓存满时的等待逻辑)。

    pop方法尝试从缓存中取出数据。如果缓存为空,它会调用not_empty.wait(data.as_mut())来阻塞当前线程,同时释放互斥锁,允许其他线程运行。当生产者线程调用push方法并向缓存中添加数据时,它会调用not_empty.notify_one()来唤醒可能正在等待的消费者线程。

    这样,我们就实现了一个简单的信号量机制,它允许消费者线程在缓存有数据时获取数据,并在没有数据时等待。

  • 相关阅读:
    Matlab:Matlab编程语言的简介、安装、学习路线(几十项代码编程案例分析)之详细攻略
    数据库中存储bool对象的数据,使用Bit和Integer有什么区别,性能上有多大的差异
    数据库之关系运算和完整性约束(软考中级)
    【力扣10天SQL入门】Day2
    docker&kubernets篇(十八)
    Git使用总结
    嵌入式实时操作系统的设计与开发 (邮箱)
    数据结构(一) -- 队列
    基于Web的个人网页响应式页面设计与实现 HTML+CSS+JavaScript(web前端网页制作课作业)
    232.用栈实现队列(LeetCode)
  • 原文地址:https://blog.csdn.net/quicmous/article/details/136505468