Rust - 跨多个线程写入向量的索引
Rust - writing to indices of a vector across multiple threads
我有一个圆形环形缓冲区(作为向量实现),我希望一个线程定期写入环形缓冲区,另一个线程定期从环形缓冲区读取。是否可以创建一个可以同时读取和写入的向量,只要访问该向量的线程不在同一索引处?
我希望达到的目标:
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
fn main() {
let vec = Arc::new(vec![Mutex::new(1), Mutex::new(2),Mutex::new(3)]);
{
let vec = vec.clone();
thread::spawn(move|| {
let mut s2 = *vec.get_mut(2).unwrap().lock().unwrap();
s2 = 7;
});
}
println!("{}", vec[2].lock().unwrap());
}
编译器输出为:
Compiling playground v0.0.1 (/playground)
warning: variable `s2` is assigned to, but never used
--> src/main.rs:12:21
|
12 | let mut s2 = *vec.get_mut(2).unwrap().lock().unwrap();
| ^^
|
= note: `#[warn(unused_variables)]` on by default
= note: consider using `_s2` instead
warning: value assigned to `s2` is never read
--> src/main.rs:13:13
|
13 | s2 = 7;
| ^^
|
= note: `#[warn(unused_assignments)]` on by default
= help: maybe it is overwritten before being read?
error[E0596]: cannot borrow data in an `Arc` as mutable
--> src/main.rs:12:27
|
12 | let mut s2 = *vec.get_mut(2).unwrap().lock().unwrap();
| ^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::sync::Arc<std::vec::Vec<std::sync::Mutex<i32>>>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0596`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.
被试图防止竞争条件的生锈类型系统挫败:(
我不想要的
- 涉及具有包含向量的锁定范围的实现。
- 不能选择对矢量进行原子读写,因为矢量将包含图像。
Link 去游乐场:
首先,我推荐你使用std::sync::RwLock
,因为它允许多个reader同时读取数据。
其次,生成线程会导致代码出现性能瓶颈。尝试使用线程池。
当然,具体的选择会根据基准测试的结果而有所不同,但这些都是一般性建议。
除了一个关键部分,你的代码大部分都是正确的。您正在使用 Mutex
实现 interior mutability 模式并提供线程安全。
内部可变性将 XOR
借用规则(N 个不可变借用或仅一个可变)的编译时检查移至 运行 时间。因此,Mutex
确保任何时候都只存在一个 reader 或只有一个作者。
当您尝试从 vec
获取可变引用时,像这样
vec.get_mut(..)
您基本上忽略了内部可变性提供的好处。编译器不能保证 XOR
规则没有被破坏,因为你借用了 vec
作为可变的。
明显的解决方案是借用 vec
作为不可变的并使用 Mutex
来防止竞争条件并且不使用编译器借用规则。
let mut s2 = vec
.get(2) // Get immutable reference to second item
.unwrap() // Ensure that it exists
.lock() // Lock mutex.
.unwrap(); // Ensure mutex isn't poisoned.
// s2 is now `std::sync::MutexGuard<i32>`, which implements `std::ops::DerefMut`,
// so it can get us mutable reference to data.
*s2 = 7;
我有一个圆形环形缓冲区(作为向量实现),我希望一个线程定期写入环形缓冲区,另一个线程定期从环形缓冲区读取。是否可以创建一个可以同时读取和写入的向量,只要访问该向量的线程不在同一索引处?
我希望达到的目标:
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
fn main() {
let vec = Arc::new(vec![Mutex::new(1), Mutex::new(2),Mutex::new(3)]);
{
let vec = vec.clone();
thread::spawn(move|| {
let mut s2 = *vec.get_mut(2).unwrap().lock().unwrap();
s2 = 7;
});
}
println!("{}", vec[2].lock().unwrap());
}
编译器输出为:
Compiling playground v0.0.1 (/playground)
warning: variable `s2` is assigned to, but never used
--> src/main.rs:12:21
|
12 | let mut s2 = *vec.get_mut(2).unwrap().lock().unwrap();
| ^^
|
= note: `#[warn(unused_variables)]` on by default
= note: consider using `_s2` instead
warning: value assigned to `s2` is never read
--> src/main.rs:13:13
|
13 | s2 = 7;
| ^^
|
= note: `#[warn(unused_assignments)]` on by default
= help: maybe it is overwritten before being read?
error[E0596]: cannot borrow data in an `Arc` as mutable
--> src/main.rs:12:27
|
12 | let mut s2 = *vec.get_mut(2).unwrap().lock().unwrap();
| ^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::sync::Arc<std::vec::Vec<std::sync::Mutex<i32>>>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0596`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.
被试图防止竞争条件的生锈类型系统挫败:(
我不想要的
- 涉及具有包含向量的锁定范围的实现。
- 不能选择对矢量进行原子读写,因为矢量将包含图像。
Link 去游乐场:
首先,我推荐你使用std::sync::RwLock
,因为它允许多个reader同时读取数据。
其次,生成线程会导致代码出现性能瓶颈。尝试使用线程池。
当然,具体的选择会根据基准测试的结果而有所不同,但这些都是一般性建议。
除了一个关键部分,你的代码大部分都是正确的。您正在使用 Mutex
实现 interior mutability 模式并提供线程安全。
内部可变性将 XOR
借用规则(N 个不可变借用或仅一个可变)的编译时检查移至 运行 时间。因此,Mutex
确保任何时候都只存在一个 reader 或只有一个作者。
当您尝试从 vec
获取可变引用时,像这样
vec.get_mut(..)
您基本上忽略了内部可变性提供的好处。编译器不能保证 XOR
规则没有被破坏,因为你借用了 vec
作为可变的。
明显的解决方案是借用 vec
作为不可变的并使用 Mutex
来防止竞争条件并且不使用编译器借用规则。
let mut s2 = vec
.get(2) // Get immutable reference to second item
.unwrap() // Ensure that it exists
.lock() // Lock mutex.
.unwrap(); // Ensure mutex isn't poisoned.
// s2 is now `std::sync::MutexGuard<i32>`, which implements `std::ops::DerefMut`,
// so it can get us mutable reference to data.
*s2 = 7;