先用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));
}
上面看到的结果,没毛病了。其实不然,…
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,ReadGuard,Values};
use std::sync::RwLock;
use std::hash::{BuildHasher, Hash};
#[macro_use]
extern crate lazy_static;
lazy_static! {
static ref HASHMAP: HashMap<u32,String> = {
let mut m = HashMap::new();
m.insert(0, "foo".into());
m.insert(1, "bar".into());
m.insert(2, "baz".into());
m
};
//static ref COUNT: usize = HASHMAP.len();
//static ref NUMBER: u32 = times_two(21);
}
// 关于读值
fn main(){
let (book_reviews_r, mut book_reviews_w) = evmap::new::<String,i32>();
//book_reviews_w => WriteHandle { epochs: Mutex { data: Slab { len: 2, cap: 2 } }, w_handle: Some(Inner { data: {}, meta: (), ready: true }), oplog: [], swap_index: 0, r_handle: ReadHandle}
//book_reviews_r => ReadHandle { epochs: Mutex { data: Slab { len: 2, cap: 2 } }, epoch: 0, my_epoch: 0 }
let w = Arc::new(Mutex::new(book_reviews_w));
println!("start writing.....including reading....");
for i in 0..10{
let w = w.clone();
let r = book_reviews_r.clone();
let code = "IF0001".to_string();
thread::spawn(move || {
let mut w = w.lock().unwrap();
let l = r.len();
match l {
0 => {
println!("0 => l:{:?}",l);
let code = code.clone();
w.insert(code, i);
println!("thread :{:?} => 0, insert =>{:?}",i,i);
w.refresh();
},
_=>{
println!("l:{:?}",l);
w.refresh();
let value = r.get(&code);//=> get => Option<ReadGuard<'rh, Values<V, S>>>
match value {
Some(rgd) =>{ //ReadGuard<'rh, Values<V, S>>
let mut v = (&*rgd).clone(); // 读值
println!("value =>{:?}",v);
w.insert(code.clone(),i);
w.refresh();
},
None =>{
println!("none=>");
w.insert(code, i);
w.refresh();
}
}
},
}
});
}
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));
}