gpt4 book ai didi

c - 多线程中某些内容的延迟失效

转载 作者:行者123 更新时间:2023-11-30 17:00:18 24 4
gpt4 key购买 nike

我的程序的每个线程都有自己的日志文件。在我的 SIGHUP 处理程序中,我想通知这些线程,当新的日志消息到达时,它们需要重新打开日志文件。

我想要一个纯粹基于标志和计数器的无锁解决方案。 (我确实有一个用于其他目的的线程本地上下文结构,因此我可以在那里添加新字段)。

如果只有一个日志线程,我会这样做:

static int need_reopen = 0;

void sighancont(int signo)
...
case SIGHUP:
need_reopen = 1;
break;
...
}

void log(char *msg) {
if (need_reopen) {
need_reopen = 0;
reopen_log();
}
...
}

当然,如果有多个日志线程,简单的标志是不行的。我正在考虑这样的事情:

static volatile int reopen_counter = 0;

void sighancont(int signo)
...
case SIGHUP:
__sync_fetch_and_add(&reopen_counter, 1);
break;
...
}

void log(struct ctx_st *ctx, char *msg) {
int c = reopen_counter;
if (ctx->reopen_counter != c) {
ctx->reopen_counter = c;
reopen_log();
}
...
}

这样,日志记录线程应该能 catch 全局计数器。如果程序多次收到SIGHUP,日志文件只会重新打开一次。

我发现打破这个问题的唯一方法是发送 SIGHUP 约 40 亿次。

是否有更好(但仍然简单)的算法,例如使用引用计数?

最佳答案

您的解决方案简单而高效。这是一种序列锁。

一些注释,以消除评论中可能出现的困惑:

  1. 没有“原子变量”,只有原子指令。 std::atomic 和 friend 们只是围绕原子操作的语法糖 - 你完全没问题。
  2. 计数器不必是 volatile 的,但访问必须是 volatile 的。当你写atomic_read(x)时,你实际上说的是*(volatile int*)&x。 volatile 限定符导致对变量的所有访问都从内存中完成,但您不一定需要这样做。但是,在这里,你也完全没问题,因为你将变量读入本地。
  3. 如果这是唯一的编写器,您可以以非原子方式更新计数器(如果删除 volatile ,请不要忘记将其设置为 atomic_write)。这将是一个非常小的性能改进。
  4. 这里唯一的成本是在计数器更新后必须为主内存访问付费的日志线程。您应该预计 200 个周期左右(其他 NUMA 节点上的 x2)

关于c - 多线程中某些内容的延迟失效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37704083/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com