我正在尝试翻译一个使用Bank对象的C程序,该程序使用的方法可以更改帐户的余额并使用互斥锁,因此这可以并行发生。在这个程序中,每个帐户都有一个锁,我需要在修改数据之前访问它。在C中,Bank对象是全局的,有许多锁来保护数据。在Rust中,我创建了一个Struct Bank,在那里我尝试使用Arc<Mutex>和Mutex,以解决将数据移动到线程的问题,因为它不实现Copy。我完全知道我可以只放入Arc<Mutex>,但为了使其更类似于C++代码,我想尝试只保护特定数据。下面是一些代码:
Bank.rs
use std::sync::{ Arc, Mutex };
#[derive(Debug)]
pub struct Account {
account_id: i32,
balance: Arc<Mutex<i64>>,
}
#[derive(Debug)]
pub struct Bank {
num: Arc<Mutex<i32>>,
num_succ: Arc<Mutex<i32>>,
num_fail: Arc<Mutex<i32>>,
accounts: Vec<Account>,
}
pub fn init(n: i32) -> Bank {
let mut accounts: Vec<Account> = Vec::new();
for i in 0..n {
accounts.push(Account {
account_id: i,
balance: Arc::new(Mutex::new(0)),
});
}
Bank {
num: Arc::new(Mutex::new(0)),
num_succ: Arc::new(Mutex::new(0)),
num_fail: Arc::new(Mutex::new(0)),
accounts: accounts,
}
}
impl Bank {
pub fn print_account(&self) {
for i in &self.accounts {
let balance_lock = i.balance.lock().unwrap();
println!("ID# {} | {}", i.account_id, balance_lock);
}
println!(
"Success: {} Fails: {}",
self.num_succ.lock().unwrap(),
self.num_fail.lock().unwrap(),
);
}
pub fn record_succ(&self, message: String) {
let mut succ_lock = self.num_succ.lock().unwrap();
println!("{message}");
*succ_lock+=1;
}
pub fn record_fail(&self, message: &str) {
let mut fail_lock = self.num_fail.lock().unwrap();
println!("{message}");
*fail_lock+=1;
}
pub fn deposit(&self, worker_id: i32, ledger_id: i32, account_id: i32, amount: i32) {
let account = self.accounts.get(account_id as usize).unwrap();
let mut balance_lock = account.balance.lock().unwrap();
*balance_lock += amount as i64;
self.record_succ(format!("Worker {worker_id} completed ledger {ledger_id}: deposit {} into account {account_id}", *balance_lock));
}
}
字符串
main.rs
use std::{
process,
thread,
env,
};
use crate::bank::*;
pub mod bank;
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 3 {
eprintln!("Usage: {} <num_of_threads>\n", args[0]);
process::exit(1);
}
let num = args[1].parse::<i32>().unwrap_or(-1);
let bank = bank::init(10);
let mut workers = Vec::new();
for id in 0..num {
// ERROR on move: move occurs because `bank` has type `bank::Bank`, which does not implement the `Copy` trait
let worker = thread::spawn(move || worker(id, &bank));
workers.push(worker);
}
for worker in workers {
worker.join().unwrap();
}
}
fn worker(worker_id: i32, bank: &Bank) {
let mut size = i32::MAX;
bank.deposit(worker_id, 0, 1, 800);
}
型
我们的目标是锁定特定的账户余额并并行修改。我有几个方法可以对自己进行这些操作。
1条答案
按热度按时间zbq4xfa01#
不需要对每个字段都使用
Arc<Mutex>
,只使用Mutex
,并将整个Bank
Package 在Arc
中。然后您可以克隆它:字符串