Rust解决Bug错误“error: future cannot be sent between threads safely”

介绍:

在开发过程中,我们可能会遇到错误消息: “error: future cannot be sent between threads safely”。这个错误通常是由于使用了不可发送(not Send)的类型引起的,尤其是 std::sync::MutexGuard 类型。这意味着我们不能将一个互斥锁(mutex)在不同线程间进行传递,而 Tokio 运行时又允许任务在每个 .await 点之间在不同线程间移动。因此,我们需要重新组织代码以确保互斥锁的析构函数在 .await 之前运行,以避免出现此错误。

还有另外一种方案是使用 tokio::task::LocalSet。通过使用 LocalSet,你可以确保异步任务只在单个线程上运行,而不需要实现 Send。这对于需要任务始终在同一线程上访问特定资源的情况非常有用。

范例一:

下面我们提供了一个范例来说明可以解决该问题的正确代码和错误代码。

正确代码:

use std::sync::{Mutex, MutexGuard};

async fn ictester_main(mutex: &Mutex<i32>) {
    {
        let mut lock: MutexGuard<i32> = mutex.lock().unwrap();
        *lock += 1;
    } // 在这里,互斥锁的析构函数会在.await之前运行,并释放锁
 
    http_get_request_async().await;
}

错误代码:

use std::sync::{Mutex, MutexGuard};
 
async fn ictester_main(mutex: &Mutex<i32>) {
    let mut lock: MutexGuard<i32> = mutex.lock().unwrap();
    *lock += 1;
    drop(lock); // 这种方式是错误的
 
    http_get_request_async().await;
}

范例二:

另一种解决方案是使用 tokio::task::LocalSet。通过使用 LocalSet,你可以确保异步任务只在单个线程上运行,而不需要实现 Send。这对于需要任务始终在同一线程上访问特定资源的情况非常有用。

use tokio::task::LocalSet;

// ...

let mut local_set = LocalSet::new();
local_set.spawn_local(ictester_main(yourI32Param.clone()));

let out = local_set.await;

在上面的代码中,我们创建了一个 LocalSet,然后使用 spawn_local() 方法将异步任务 ictester_main() 添加到 LocalSet 中。这确保了该任务将在同一线程上运行,从而避免了错误:“error: future cannot be sent between threads safely”。

注意事项

  1. 在使用互斥锁(Mutex)时,务必在任务的关键点上正确释放锁。最佳实践是确保互斥锁的析构函数在.await之前运行,以确保锁被正确释放。可以通过在互斥锁的作用域内使用大括号来控制互斥锁的生命周期。
  2. 避免在异步任务中手动调用drop函数来释放互斥锁。手动调用drop函数会导致互斥锁被提前释放,可能会导致错误,因为互斥锁不应该在异步的上下文中手动释放。
  3. 当使用tokio::task::LocalSet来确保异步任务在同一线程上运行时,需要注意,该方式适用于在同一线程上访问特定资源的情况。

总结:

在解决 “error: future cannot be sent between threads safely” 类似的错误时,我们应该避免将不可发送类型引入跨线程的异步任务中。这可以通过确保互斥锁的析构函数在 .await 之前运行,或者使用 tokio::task::LocalSet 等方法来限制任务的运行范围。通过合理组织代码,我们可以避免这种错误,并确保程序的线程安全性。

除了通过重新组织代码以确保互斥锁在 .await 前释放以避免错误外,还可以使用 tokio::task::LocalSet 来限制异步任务的运行范围。这样可以确保任务始终在同一线程上运行,而无需实现 Send。根据具体情况选择适合的解决方案,以确保代码的正确性和线程安全性。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

热心码民阿振

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值