先用evmap上的例子来尝试
Cargo.toml
evmap = "10.0.2"
一、模式探讨
1、多写多读模式一:
use parking_lot::*;
use std::thread;
use std::sync::{Arc, Mutex};
use std::time;
use std::collections::{HashMap};
extern crate evmap;
use evmap::{ReadHandle, WriteHandle};
fn main(){
let (book_reviews_r, mut book_reviews_w) = evmap::new();
//多写
let writer_n =4;
let w = Arc::new(Mutex::new(book_reviews_w));
let writers: Vec<_> = (0..writer_n).map(|i| {
let w = w.clone();
thread::spawn(move || {
let mut w = w.lock().unwrap();
w.insert(i.to_string(), i); // 数据的结构,key,value
w.refresh();
})
}).collect();
// 多读
let reader_n =50;
let readers: Vec<_> = (0..reader_n).map(|_| {
let r = book_reviews_r.clone();
thread::spawn(move || {
loop {
let l = r.len();
if l == 0 {
thread::yield_now();// 放弃
} else {
println!("--------------------------- start");
println!("r ---> : {:?}", l);
for (book, reviews) in &r.read().unwrap() {
for review in reviews {
println!("{}: \"{}\"", book, review);
}
}
println!("--------------------------- end");
break;
}
}
})
}).collect();
std::thread::sleep(std::time::Duration::from_secs(1000)); // 需要在主线程上停留足够时间
}
在这种情况下,读是完全一样的。感觉是已经写完之后,再去读的。
2、多写多读模式2:边写边读模式
为了更加真实,在读和写放在一个循还不同的二个线程中。
fn main(){
let (book_reviews_r, mut book_reviews_w) = evmap::new();
let w = Arc::new(Mutex::new(book_reviews_w));
for i in 0..5{
let r = book_reviews_r.clone();
thread::spawn(move || {
loop {
let l = r.len();
if l == 0 {
thread::yield_now();// 放弃
} else {
println!("--------------------------- start");
println!("r ---> : {:?}", l);
for (book, reviews) in &r.read().unwrap() {
for review in reviews {
println!("{}: \"{}\"", book, review);
}
}
println!("--------------------------- end");
break;
}
}
});
let w = w.clone();
thread::spawn(move || {
let mut w = w.lock().unwrap();
w.insert(i.to_string(), i);
w.refresh();
});
}
std::thread::sleep(std::time::Duration::from_secs(100));
}
可以看到,在这种情况下,更象是是边写边读的。
大家想想看,有什么问题?r和真实的不一样!
3、模式3
fn main(){
let (book_reviews_r, mut book_reviews_w) = evmap::new();
let w = Arc::new(Mutex::new(book_reviews_w));
for i in 0..5{
// 先放写
let w = w.clone();
thread::spawn(move || {
let mut w = w.lock().unwrap();
w.insert(i.to_string(), i);
w.refresh();
});
//后放读
let r = book_reviews_r.clone();
thread::spawn(move || {
loop {
let l = r.len();
if l == 0 {
thread::yield_now();// 放弃
} else {
// the reader will either see all the reviews,
// or none of them, since refresh() is atomic.
//w.refresh();
println!("--------------------------- start");
println!("r ---> : {:?}", l);
for (book, reviews) in &r.read().unwrap() {
for review in reviews {
println!("{}: \"{}\"", book, review);
}
}
println!("--------------------------- end");
break;
}
}
});
}
std::thread::sleep(std::time::Duration::from_secs(100));
}
二、关于重要的方法
book_reviews_r 可用的方法有:
read();
get(),
clone();
len()
get_meta()
contains_key()
mut book_reviews_w可用的方法有:
refresh(),
insert(),
clone()
remove_value()
remove_keys()
retain()
remove_entry()
update()
clear()
extend()
r.read().unwrap().keys()
r.read().unwrap().values()
具体见:
https://github.com/jonhoo/rust-evmap/blob/master/tests/lib.rs
fn main(){
//run::strategy_run().unwrap();
//std::thread::sleep(std::time::Duration::from_secs(10000));
let (book_reviews_r, mut book_reviews_w) = evmap::new();
let w = Arc::new(Mutex::new(book_reviews_w));
for i in 0..5{
let w = w.clone();
thread::spawn(move || {
let mut w = w.lock().unwrap();
let mut v = Vec::new();
v.push(i);
w.insert(i.to_string(), v);
w.update(i.to_string(), vec![i,i+1]);
w.refresh();
});
let r = book_reviews_r.clone();
//r.refresh();
let l = r.len();
println!("r ---> : {:?}", l);
thread::spawn(move || {
loop {
println!("--------------------------- start");
for (book, reviews) in &r.read().unwrap() {
println!("{:?}: \"{:?}\"", book, reviews);
}
println!("--------------------------- end");
break;
}
});
}
std::thread::sleep(std::time::Duration::from_secs(100));
}