如何在 Rust 中运行同步代码(一次一个线程)?

问题描述 投票:0回答:1

我正在使用 warp web 框架和 tokio 异步运行时在 Rust 中构建一个 Rest API,问题是我的代码中有一系列操作,其中线程无法同时执行所有操作,它们需要一次执行一个时间,我该如何在 Rust 中做到这一点?

这是需要锁定的代码块:

async fn execute() {
    client_dao.get_client(id);
    let new_balance = calculate_new_balance();
    client_dao.transaction(id, new_balance, transaction_entity);
}

我的尝试:

use std::sync::Mutex

async fn execute() {
    let mutex = Mutex::new(0);
    let _guard = mutex.lock().unwrap();

    client_dao.get_client(id);
    let new_balance = calculate_new_balance();
    client_dao.transaction(id, new_balance, transaction_entity);
}

这导致我收到错误:

async function: the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, Client>`

在这个链接中https://stackoverflow.com/a/67277503/12253990我看到通过使用异步运行时,我需要使用为异步制作的互斥体,所以我尝试了这个:

use tokio::sync::Mutex;

async fn execute() {
    let mutex = Mutex::new(0);
    let _guard = mutex.lock().await;

    client_dao.get_client(id);
    let new_balance = calculate_new_balance();
    client_dao.transaction(id, new_balance, transaction_entity);
}

它没有给我错误,但是互斥锁不起作用,存在竞争条件错误...我使用 k6 编写了一个脚本,该脚本同时调用端点两次,传递值 50,客户端余额为 0 ,也就是说,最终的余额应该是100,但是最终的余额是50,因为线程之间互相运行......

我尝试过的另一件事:

use tokio::sync::Mutex;
use std::sync::Arc;

async fn execute() {
    let mutex = Arc::new(Mutex::new(0));
    let _guard = mutex.lock().await;

    client_dao.get_client(id);
    let new_balance = calculate_new_balance();
    client_dao.transaction(id, new_balance, transaction_entity);
}

同样的事情,没有错误,但竞争条件继续发生,线程不是一次执行一个,但我该如何在 Rust 中做到这一点?

multithreading rust concurrency mutex thread-synchronization
1个回答
0
投票

我使用存储函数解决了这个问题,我将处理和业务规则留在数据库中,因为我可以阻止其他事务选择更新的记录,直到当前事务完成,即一次只能有一个事务可以修改所选数据,这避免了竞争条件

© www.soinside.com 2019 - 2024. All rights reserved.