forum icon indicating copy to clipboard operation
forum copied to clipboard

【Zig 日报】在两个线程之间共享数据

Open jiacai2050 opened this issue 11 months ago • 5 comments

当我们要更改线程之间共享的数据时,必须使用 Mutex(互斥标志,Mutually exclusive)来同步线程,否则结果可能出乎意料。

const std = @import("std");
const Thread = std.Thread;
const Mutex = Thread.Mutex;

const SharedData = struct {
    mutex: Mutex,
    value: i32,

    pub fn updateValue(self: *SharedData, increment: i32) void {
        // Use `tryLock` if you don't want to block
        self.mutex.lock();
        defer self.mutex.unlock();

        for (0..100) |_| {
            self.value += increment;
        }
    }
};

pub fn main() !void {
    var shared_data = SharedData{ .mutex = Mutex{}, .value = 0 };
    // This block is necessary to ensure that all threads are joined before proceeding.
    {
        const t1 = try Thread.spawn(.{}, SharedData.updateValue, .{ &shared_data, 1 });
        defer t1.join();
        const t2 = try Thread.spawn(.{}, SharedData.updateValue, .{ &shared_data, 2 });
        defer t2.join();
    }
    try std.testing.expectEqual(shared_data.value, 300);
}

如果我们取消 Mutex 保护,结果很可能小于 300。

加入我们

Zig 中文社区是一个开放的组织,我们致力于推广 Zig 在中文群体中的使用,有多种方式可以参与进来:

  1. 供稿,分享自己使用 Zig 的心得
  2. 改进 ZigCC 组织下的开源项目
  3. 加入微信群

jiacai2050 avatar Jan 10 '25 12:01 jiacai2050

注释掉那两行代码,运行了很多遍也没失败;加入 yield 才看到预期行为。

hshq avatar Jan 10 '25 17:01 hshq

估计你电脑速度太快了,可以试试把lock 放循环里面试试

jiacai2050 avatar Jan 11 '25 01:01 jiacai2050

估计你电脑速度太快了,可以试试把lock 放循环里面试试

不能啊,我用的是 macmini m2 。 另外,注释掉已经不生效了,放在哪里都一样啊。

hshq avatar Jan 11 '25 04:01 hshq

加入sleep,或者扩大循环次数。这是一个概率出现的现象,竞争,多试几次

not-a-fan avatar Jan 13 '25 15:01 not-a-fan

加入sleep,或者扩大循环次数。这是一个概率出现的现象,竞争,多试几次

放大 100 倍可以了。

hshq avatar Jan 13 '25 18:01 hshq