BEGINNING RUST PROGRAMMING
Author: Ric Messier
如果需要电子书的小伙伴,可以留下邮箱,看到了会发送的
Chapter 5 In Concurrence
Mutexes and Semaphores
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let data = Arc::new(Mutex::new(0));
for _ in 0..15 {
let data = Arc::clone(&data);
thread::spawn(move || {
let mut data = data.lock().unwrap();
*data += 1;
if *data == 15 {
return
}
});
}
}
锁的使用,其实就是将一个变量,或者说是一块内存,放在了一个盒子里面,外面上了锁,如果多个线程想要同时访问这块内存,那么只有拿到钥匙的那个线程才可以进去,这就是Mutex
的作用
至于Mutex
外面的那一层,是Arc
,全称是atomically reference counted,也就是自动引用计数器,根据前面的篇章我们知道,在Rust中,变量是由所有权的,如果想要在多线程环境下,提供给多个线程同时使用,那就需要一个引用计数器,方便这个内存的释放,以防止访问到非法内存
thread::spawn
就是衍生线程的意思,相当于Java中的new Thread()
move || {}
而这个是一个闭包,就类似于一个匿名函数,两个竖线就是入参的位置,只是现在没有入参,而前面的move
,代表在闭包中所使用的外部环境的变量,所有权会转移到闭包内部
而代码的内部,*
的使用,是因为.lock().unwrap()
所返回的是数据的引用,如果想要使用,就需要解引用,*
在这里是解引用符
Interprocess Communications
这里说了进程间通信(IPC)的方法
第一种是channel
,而且是MPSC,也即是多生产者单消费者的通道
use std::sync::mpsc;
fn main() {
let (snd, rcv) = mpsc::channel();
snd.send("Wubble wubble foo").unwrap();
println!("Message is: {}", rcv.recv().unwrap());
}
另一种是Unix sockets
,不过它的核心思想都差不多,这种信息的传输,只不过是两个线程间或者两个进程间对同一块内存的顺序访问,在线程间,那就是对同一种数据结构的访问,在进程间,就是对同一个文件的访问,因为在Unix中,一切皆文件,所以其实Unix sockets
也像是一种文件,本来不同进程是不能访问对方的内存的,现在有个文件两个进程都能访问,所以就可以通信了
extern crate sha2;
use std::thread;
use std::{env, fs};
use std::fs::{ReadDir,DirEntry};
use sha2::{Sha256, Digest};
use std::os::unix::net::{UnixStream, UnixListener};
use std::io::Read;
use std::io::Write;
use std::path::Path;
use std::process;
fn sock_server(mut listener: UnixStream) {
loop {
let mut response = String::new();
let _length = listener.read_to_string(&mut response).unwrap();
println!("{}", response);
}
}
fn get_files(path: &String) -> ReadDir {
fs::read_dir(&path).unwrap()
}
fn read_file(filename: &fs::DirEntry) -> Result<String, ()> {
if !filename.path().is_dir() {
let contents = match fs::read_to_string(filename.path()) {
Ok(contents) => contents,
Err(why) => panic!("{:?}", filename.path())
};
Ok(contents)
}
else {
Err(())
}
}
fn main() -> Result<(),()> {
let current_dir = String::from(env::current_dir().unwrap().to_str().unwrap());
let (mut side1, mut side2) = match UnixStream::pair() {
Ok((side1, side2)) => (side1, side2),
Err(e) => {
println!("Couldn't create a pair of sockets: {:?}", e);
std::process::exit(-1);
}
};
let serv_handle = thread::spawn( || { sock_server(side1) });
for file in get_files(¤t_dir) {
let entry = file.unwrap();
if let Ok(file) = read_file(&entry) {
let msg = format!("{} : {:x}", entry.path().to_str().unwrap(),
Sha256::digest(file.as_bytes()));
side2.write_all(&msg.into_bytes());
}
}
Ok(())
}
标签:std,use,unwrap,PROGRAMMING,---,let,path,data,随记
From: https://www.cnblogs.com/huangwenhao1024/p/16927121.html