tokio 的 RwLock 保护的多个字段的序列化
Serialization of multiple fields protected by tokio's RwLock
我使用 tokio 来监听 UDP 套接字。我 send/receive bincode
编码结构和 serialize/deserialize 它们 serde
.
但是我应该如何处理 Arc<tokio::sync::RwLock<T>>
字段的序列化? (我知道 serde 支持标准库同步 RwLock
但我需要异步)。
数据经常被更改并通过网络传输(按设计),因此每次我需要发送内容时等待多个读锁可能不是一个好主意。
考虑到 serde 是同步的,我必须为每个 RwLock
字段生成阻塞 tokio 任务。 (每个字段都有自己的 RwLock
个字段)。所以这会变得非常慢。
rust 处理这个问题的方法是什么?
示例:
use serde::{Deserialize, Serialize};
use tokio::sync::RwLock;
#[derive(Serialize, Deserialize)]
struct Player {
// In order to serialize Player i'd have to one by one acquire lock for `meta` and then `stats`, and then some other potential fields.
pub id: u64,
pub meta: Arc<RwLock<Metadata>>,
pub stats: Arc<RwLock<Metadata>>,
pub someOtherField1: Arc<RwLock<...>>,
pub someOtherField2: Arc<RwLock<...>>,
pub someOtherField3: Arc<RwLock<...>>,
}
Data is being changed and transferred over the network fairly often (by design), so it's probably not a good idea to wait for multiple read locks every time i need to send something.
忘记性能 - 这不会成为您在任何类型的游戏网络中的瓶颈(这确实出现了您正在尝试做的事情)。
唯一正确的方法是先在序列化数据之前对每个字段获取读锁,然后将它们全部序列化。如果你不这样做,你最终会得到不一致的状态 ,在逻辑上不存在 。玩家可能还活着但生命值为 0,或者在游戏中已断开连接。
这可能会导致死锁!这是您开始共享数据时选择的难度。有一个非常好的经验法则可以防止死锁,如果你虔诚地坚持它,你必须在你的代码中做到这一点:任何获取多个锁的例程都必须以相同的顺序获取它们。 如果需要一个新锁,但我们已经有其他锁在顺序后面,我们必须先释放所有锁,然后再以正确的顺序再次获取它们。
坚持上述做法的最简单方法是只为玩家设置一把锁。
我使用 tokio 来监听 UDP 套接字。我 send/receive bincode
编码结构和 serialize/deserialize 它们 serde
.
但是我应该如何处理 Arc<tokio::sync::RwLock<T>>
字段的序列化? (我知道 serde 支持标准库同步 RwLock
但我需要异步)。
数据经常被更改并通过网络传输(按设计),因此每次我需要发送内容时等待多个读锁可能不是一个好主意。
考虑到 serde 是同步的,我必须为每个 RwLock
字段生成阻塞 tokio 任务。 (每个字段都有自己的 RwLock
个字段)。所以这会变得非常慢。
rust 处理这个问题的方法是什么?
示例:
use serde::{Deserialize, Serialize};
use tokio::sync::RwLock;
#[derive(Serialize, Deserialize)]
struct Player {
// In order to serialize Player i'd have to one by one acquire lock for `meta` and then `stats`, and then some other potential fields.
pub id: u64,
pub meta: Arc<RwLock<Metadata>>,
pub stats: Arc<RwLock<Metadata>>,
pub someOtherField1: Arc<RwLock<...>>,
pub someOtherField2: Arc<RwLock<...>>,
pub someOtherField3: Arc<RwLock<...>>,
}
Data is being changed and transferred over the network fairly often (by design), so it's probably not a good idea to wait for multiple read locks every time i need to send something.
忘记性能 - 这不会成为您在任何类型的游戏网络中的瓶颈(这确实出现了您正在尝试做的事情)。
唯一正确的方法是先在序列化数据之前对每个字段获取读锁,然后将它们全部序列化。如果你不这样做,你最终会得到不一致的状态 ,在逻辑上不存在 。玩家可能还活着但生命值为 0,或者在游戏中已断开连接。
这可能会导致死锁!这是您开始共享数据时选择的难度。有一个非常好的经验法则可以防止死锁,如果你虔诚地坚持它,你必须在你的代码中做到这一点:任何获取多个锁的例程都必须以相同的顺序获取它们。 如果需要一个新锁,但我们已经有其他锁在顺序后面,我们必须先释放所有锁,然后再以正确的顺序再次获取它们。
坚持上述做法的最简单方法是只为玩家设置一把锁。