advance/concurrency-with-threads/sync2 #734
Replies: 22 comments 30 replies
-
我看到这里了耶, 💯 |
Beta Was this translation helpful? Give feedback.
-
我用Go语言跑了一下自增的例子,大概花费了200ms,但是用rust里面的Atomic要花费4s左右,怎么差这么多哦 |
Beta Was this translation helpful? Give feedback.
-
use std::ops::Sub;
use std::sync::{Mutex, Arc};
use std::thread::{self, JoinHandle};
use std::time::Instant;
const N_TIMES: u64 = 10_000_000;
const N_THREADS: usize = 10;
fn add_n_times(n: u64, counter: Arc<Mutex<u64>>) -> JoinHandle<()> {
thread::spawn(move || {
for _ in 0..n {
let mut num = counter.lock().unwrap();
*num += 1;
}
})
}
fn main() {
let mut counter: Arc<Mutex<u64>> = Arc::new(Mutex::new(0));
let s = Instant::now();
let mut threads = Vec::with_capacity(N_THREADS);
for _ in 0..N_THREADS {
threads.push(add_n_times(N_TIMES, counter.clone()))
}
for thread in threads {
thread.join().unwrap();
}
assert_eq!(N_TIMES * N_THREADS as u64, *counter.lock().unwrap());
println!("{:?}",Instant::now().sub(s));
} 针对与第一个例子的 |
Beta Was this translation helpful? Give feedback.
-
突然就蹦出来一个变量,也不知道是啥,用方法也不说是干啥的 |
Beta Was this translation helpful? Give feedback.
-
创建线程的性能因此线程的创建耗时并不是不可忽略的 根据上下文的语境,这里应该是不应该完全忽略。 |
Beta Was this translation helpful? Give feedback.
-
这章最后一个例子用的不好, 莫明其妙的上了之前段落都没有提到过的自旋锁. |
Beta Was this translation helpful? Give feedback.
-
GPT打死不承认Atomic跨线程需要Arc,可恶 |
Beta Was this translation helpful? Give feedback.
-
Barrier是什么,为什么每一个循环都要 clone一下,这个b.wait()有什么用吗 |
Beta Was this translation helpful? Give feedback.
-
能详细说下 thread_local! 宏么? |
Beta Was this translation helpful? Give feedback.
-
对于某些没使用或者没讲过的对象能不能给个注释呀,这点可能对新手不太友好,每次一边看书,还要一边百度 |
Beta Was this translation helpful? Give feedback.
-
不科学,为什么我的使用原子类型耗时多? use std::ops::Sub;
use std::sync::{
atomic::{AtomicU64, Ordering},
Arc, Mutex,
};
use std::thread::{self, JoinHandle};
use std::time::{Duration, Instant};
const N_TIMES: u64 = 10000000;
const N_THREADS: usize = 10;
static R: AtomicU64 = AtomicU64::new(0);
fn add_n_times(n: u64) -> JoinHandle<()> {
thread::spawn(move || {
for _ in 0..n {
R.fetch_add(1, Ordering::Relaxed);
}
})
}
fn main() {
println!("use mutex: {:?}", use_mutex());
println!("use automic: {:?}", use_automic());
}
fn use_automic() -> Duration {
let s = Instant::now();
let mut threads = Vec::with_capacity(N_THREADS);
for _ in 0..N_THREADS {
threads.push(add_n_times(N_TIMES));
}
for thread in threads {
thread.join().unwrap();
}
assert_eq!(N_TIMES * N_THREADS as u64, R.load(Ordering::Relaxed));
Instant::now().sub(s)
}
fn use_mutex() -> Duration {
let s = Instant::now();
let mut threads = Vec::with_capacity(N_THREADS);
let counter: Arc<Mutex<u64>> = Arc::new(Mutex::new(0));
for _ in 0..N_THREADS {
let lock = counter.clone();
threads.push(thread::spawn(move || {
let mut num = lock.lock().unwrap();
while *num < N_TIMES * N_THREADS as u64 {
*num += 1;
}
}));
}
for thread in threads {
thread.join().unwrap();
}
assert_eq!(N_TIMES * N_THREADS as u64, *counter.lock().unwrap());
Instant::now().sub(s)
} |
Beta Was this translation helpful? Give feedback.
-
我本地跑出来的数据有点夸张了... CAS 版本 2s 左右, Mutex 版本 20s+... use std::ops::Sub;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::{Arc, Mutex};
use std::thread::{self, JoinHandle};
use std::time::Instant;
const N_TIMES: u64 = 10000000;
const N_THREADS: usize = 10;
static R: AtomicU64 = AtomicU64::new(0);
fn add_n_times(n: u64) -> JoinHandle<()> {
thread::spawn(move || {
for _ in 0..n {
R.fetch_add(1, Ordering::Relaxed);
}
})
}
fn add_n_times_mutex(n: u64, num: Arc<Mutex<u64>>) -> JoinHandle<()> {
thread::spawn(move || {
for _ in 0..n {
let mut actual_num = num.lock().unwrap();
*actual_num += 1;
}
})
}
fn main() {
let s = Instant::now();
let mut threads = Vec::with_capacity(N_THREADS);
for _ in 0..N_THREADS {
threads.push(add_n_times(N_TIMES));
}
for thread in threads {
thread.join().unwrap();
}
assert_eq!(N_TIMES * N_THREADS as u64, R.load(Ordering::Relaxed));
println!("CAS version: {:?}", Instant::now().sub(s));
println!("================================================");
let s2 = Instant::now();
let res = Arc::new(Mutex::new(0));
let mut threads = Vec::with_capacity(N_THREADS);
for _ in 0..N_THREADS {
let temp_res = res.clone();
threads.push(add_n_times_mutex(N_TIMES, temp_res));
}
for thread in threads {
thread.join().unwrap();
}
assert_eq!(N_TIMES * N_THREADS as u64, *res.lock().unwrap());
println!("Mutex version: {:?}", Instant::now().sub(s2));
} |
Beta Was this translation helpful? Give feedback.
-
javaer也来学rust了,看到自增这个例子赶忙去用java写了个test对比了一下,rust release模式试了10次跑出来平均 1.9s,java试了10次跑出来平均 1.6s,这是为啥? Rust 代码 #[test]
fn test_atomic() {
static R: AtomicU64 = AtomicU64::new(0);
const N: usize = 10;
const TIMES: u64 = 10000000;
let start = Instant::now();
let mut threads = Vec::with_capacity(N);
for _ in 0..N {
threads.push(thread::spawn(move || {
for _ in 0..TIMES {
// Ordering 是用于控制内存顺序
R.fetch_add(1, Ordering::Relaxed);
}
}));
}
for thread in threads {
thread.join().unwrap();
}
assert_eq!(N as u64 * TIMES, R.load(Ordering::Relaxed));
println!("use {:?}", Instant::now().sub(start))
} Java 代码 @Test
public void testAtomic() throws Exception {
AtomicLong counter = new AtomicLong(0);
final int N = 10;
final long TIMES = 10000000;
long start = System.currentTimeMillis();
Thread[] threads = new Thread[N];
for (int i = 0; i < N; i++) {
Thread t = new Thread(() -> {
for (long l = 0; l < TIMES; l++) {
counter.addAndGet(1);
}
});
t.start();
threads[i] =t;
}
for (Thread t : threads) {
t.join();
}
Assert.assertEquals(N * TIMES, counter.get());
System.out.println("use " + (System.currentTimeMillis() - start) + " ms");
} |
Beta Was this translation helpful? Give feedback.
-
运行结果如上,真就 main线程执行完了就结束,子线程打印到一半还没打完... |
Beta Was this translation helpful? Give feedback.
-
很不错的手册,很糟糕的教程 |
Beta Was this translation helpful? Give feedback.
-
厉害厉害,拨云见雾。 |
Beta Was this translation helpful? Give feedback.
-
条件控制那部分的执行顺序并不能保证,只是大概率主线程先执行。while有概率不执行。 |
Beta Was this translation helpful? Give feedback.
-
没有看懂内存顺序。例子和解释有点少 。。。。。。。 |
Beta Was this translation helpful? Give feedback.
-
要感谢:对于原子语义,可以在硬件层面进行说明。第一次学习到,原子指令在多核心CPU下,单个CPU在执行原子指令的时候,需要暂停其他CPU执行。这个给了我很大的启发,在硬件层面认知系统。 |
Beta Was this translation helpful? Give feedback.
-
还是叫指令重排序听得懂些,内存顺序这个名字真的奇怪 |
Beta Was this translation helpful? Give feedback.
-
advance/concurrency-with-threads/sync2
https://course.rs/advance/concurrency-with-threads/sync2.html
Beta Was this translation helpful? Give feedback.
All reactions