< 返回版块

liyiheng 发表于 2018-07-26 18:26

Tags:并发

有些不需要加锁的场景,在Rust如何实现比较好呢?

比如

dat := make([]int,10)
for i := range dat{
	go func(index int){
		dat[index] = index * index 
	}(i)
}

用消息传递太麻烦,用锁又怕有性能开销,难道只能用unsafe吗

评论区

写评论
Krys 2018-09-06 17:38

根本不用那么麻烦,几行就搞定

extern crate rayon;
use rayon::prelude::*;


fn main () {
    let mut v = vec![0; 10];
    v.par_iter_mut().enumerate().for_each(|(i, x)| *x = i * i);

    for item in &v {
        println!("{}", item);
    }
}
作者 liyiheng 2018-07-30 10:41

666

@123hc 相关学习记录 extern crate crossbeam; extern crate num_cpus; extern crate rand; extern crate rayon; use rayon::prelude::*; use std::sync::{mpsc, Arc, Mutex}; use std::thread; use std::time::{Duration, Instant}; fn main() { //可共享可更改 let data_w = Arc::new(Mutex::new(vec![0; 10])); //可共享不可更改 //let data_r = Arc::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); //消息通道 let (tx, rx) = mpsc::channel();

for i in 0..10 {
    let (data_w, tx) = (data_w.clone(), tx.clone());
    thread::spawn(move || {
        let x = rand::random::<i32>() % 220;
        let start = Instant::now();
        {
            let mut data_w = data_w.lock().unwrap();
            data_w[i] = x;
        }
        let elapsed = start.elapsed();
        tx.send((i, start, elapsed)).unwrap();
    });
}
//关闭通道
drop(tx);
for _ in 0..10 {
    let x = rx.recv().unwrap();
    println!("{:?}", x);
}
println!("{:?}", data_w);

// 用rayon
//自定义线程池
let _pool = rayon::ThreadPoolBuilder::new()
    .num_threads(num_cpus::get() + 0)
    .build()
    .unwrap();
let r = rand::random::<i32>() % 20;
println!("random:{:?}", r);
let mut data_p = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
data_p.par_iter_mut().for_each(|x| *x *= *x + r);
println!("data_p: {:?}", data_p);

//使用crossbeam mpmc
let (s, r) = crossbeam::channel::unbounded();
for i in 0..10 {
    let s = s.clone();

    thread::spawn(move || {
        s.send(i);
    });
}

for i in 0..10 {
    let r = r.clone();

    thread::spawn(move || {
        let x = r.recv().unwrap();

        println!("r{} << s{:?}", i, x);
    });
}
//主线程等待1秒
thread::sleep(Duration::from_secs(1));

}

123hc 2018-07-27 23:19

相关学习记录

extern crate crossbeam;
extern crate num_cpus;
extern crate rand;
extern crate rayon;
use rayon::prelude::*;
use std::sync::{mpsc, Arc, Mutex};
use std::thread;
use std::time::{Duration, Instant};
fn main() {
    //可共享可更改
    let data_w = Arc::new(Mutex::new(vec![0; 10]));
    //可共享不可更改
    //let data_r = Arc::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
    //消息通道
    let (tx, rx) = mpsc::channel();

    for i in 0..10 {
        let (data_w, tx) = (data_w.clone(), tx.clone());
        thread::spawn(move || {
            let x = rand::random::<i32>() % 220;
            let start = Instant::now();
            {
                let mut data_w = data_w.lock().unwrap();
                data_w[i] = x;
            }
            let elapsed = start.elapsed();
            tx.send((i, start, elapsed)).unwrap();
        });
    }
    //关闭通道
    drop(tx);
    for _ in 0..10 {
        let x = rx.recv().unwrap();
        println!("{:?}", x);
    }
    println!("{:?}", data_w);

    // 用rayon
    //自定义线程池
    let _pool = rayon::ThreadPoolBuilder::new()
        .num_threads(num_cpus::get() + 0)
        .build()
        .unwrap();
    let r = rand::random::<i32>() % 20;
    println!("random:{:?}", r);
    let mut data_p = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    data_p.par_iter_mut().for_each(|x| *x *= *x + r);
    println!("data_p: {:?}", data_p);

    //使用crossbeam mpmc
    let (s, r) = crossbeam::channel::unbounded();
    for i in 0..10 {
        let s = s.clone();

        thread::spawn(move || {
            s.send(i);
        });
    }

    for i in 0..10 {
        let r = r.clone();

        thread::spawn(move || {
            let x = r.recv().unwrap();

            println!("r{} << s{:?}", i, x);
        });
    }
    //主线程等待1秒
    thread::sleep(Duration::from_secs(1));
}

laizy 2018-07-27 13:30

消息传递还好吧。你把go版的WaitGroup加上去的话,代码差不了多少。

    let (sender, recv) = mpsc::channel();
    for i in 0..10 {
        let sender = sender.clone();
        thread::spawn(move || {
            sender.send((i, i*i)).unwrap();
        });
    }
    drop(sender);
    let mut result = vec![0;10];
    for res in recv {
        result[res.0] = res.1;
    }

@liyiheng 恩,实际上是用了WaitGroup 最近看Rust并发的方面,用起来各种不习惯,不知道是不是姿势不对 求推荐适合学习的代码

@laizy 严格来讲 go也得有相应的同步机制呀。子线程写入dat的数据应该是供main routine读取的吧。main routine啥时候去读取dat的数据?如果main routine去读的时候 子routine还没写进去呢?或者子routine也同时在写呢?这时候就有数据并发的问题。

作者 liyiheng 2018-07-27 11:14

emmmm,用unsafe的Rust是没有灵魂的。我觉得还是尽量不用

@woodensea 这个问题看见好多次了...用rayon库看看, 还有为啥那么怕unsafe, c都敢写的人们...

woodensea 2018-07-27 10:16

这个问题看见好多次了...用rayon库看看, 还有为啥那么怕unsafe, c都敢写的人们...

作者 liyiheng 2018-07-27 10:10

恩,实际上是用了WaitGroup

最近看Rust并发的方面,用起来各种不习惯,不知道是不是姿势不对

求推荐适合学习的代码

@laizy 严格来讲 go也得有相应的同步机制呀。子线程写入dat的数据应该是供main routine读取的吧。main routine啥时候去读取dat的数据?如果main routine去读的时候 子routine还没写进去呢?或者子routine也同时在写呢?这时候就有数据并发的问题。

laizy 2018-07-26 20:41

严格来讲 go也得有相应的同步机制呀。子线程写入dat的数据应该是供main routine读取的吧。main routine啥时候去读取dat的数据?如果main routine去读的时候 子routine还没写进去呢?或者子routine也同时在写呢?这时候就有数据并发的问题。

1 共 8 条评论, 1 页