【问题标题】:Accessing global variables in pthreads in different c-files访问不同 c 文件中 pthread 中的全局变量
【发布时间】:2011-11-15 00:10:51
【问题描述】:

我有一个 main.c,其中有一个名为 int countboards 的全局变量。在 main() 中,我启动了一个 pthread,它侦听 ONE TCP-Connection 并通过 (progserver.c) 运行它。意味着,该线程将永远不会返回。在 main() 中,我输入了 rm.c 中的函数 rmmain(...)(RM=Ressource Manager)。在 rm.c 中,我读取了 countboards,在 pthread 中的 progserver.c 中,我写入了这个变量(两者都可以通过 extern int countboards 访问)。

所以问题是,当我在 pthread 中写入 countboards 并且我想在它被写入 rm.c 之后访问这个变量时,它仍然具有旧值(在这种情况下是 0 而不是 for例 10)。为什么?

main.c:

int countboards;

int main(int argc, char** argv) {
  countboards = 0;
  pthread_t thread;
  pthread_create(&thread, NULL, startProgramserver, NULL);

  rmmain();

  return 0;
}

rm.c:

extern int countboards;

int rmmain(vhbuser* vhbuserlist, int countvhbuser,
       userio* useriolist, int countios, int usertorm, int rmtosslserver, int sslservertorm) {
  while(1) {
    int n;
    n=read(usertorm,buf,bufc); // blocks until command comes from the user
    ...
    board* b = findAFreeBoard(boardlist, countboards, usagelist); // here countboards should be >0, but it isn't
    ...
  }
}

programserver.c:

extern int countboards;
void* startProgramserver(void*) {
  ...
  sock = tcp_listen();
  ...
  http_serve(ssl,s, sslpipes);
}

static int http_serve(SSL *ssl, int s, void* sslpipes) {
  ...
  countboards = countboards + countboardscommands;
  ...
  // here countboards has the new value
}

【问题讨论】:

    标签: c linux pthreads global-variables posix


    【解决方案1】:

    您会在每个线程中看到一个缓存副本。我建议将其声明为volatile int countboards,除非这真的不是一个好方法。

    全局变量有点邪恶。将指针传递给每个线程并与互斥锁同步会更好地为您服务。

    编辑:由于我昨晚很匆忙,所以要对此进行扩展......

    http://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming/

    正如KasigiYabu 在下面的 cmets 中提到的那样,创建一个“上下文”结构,其中包含您想要在线程之间共享的所有信息并将其作为最后一个参数传递给 pthread_create 是一种合理的方法,并且是在大多数情况下,我也这样做。

    【讨论】:

    • 是的,它应该被声明为volatile,但它也应该被互斥体保护以确保原子性。
    • 如果它受到互斥体的读写保护,则不需要 volatile(只会损害性能)
    • 这样传球? pthread_create(&thread, NULL, startProgramserver, &countboards); 并在从 void* 回到 int 的线程中?当我有 2 个变量时怎么办?如何传递intboard 变量(board 是自制结构)?
    • 您可以创建一个 Context 结构,其中包含线程所需的所有变量,并将指针传递给该结构。无论如何,使用 volatile 可能还不够——互斥锁对我来说是必需的。可能是您的编译器为您优化了某些东西(例如,当您使用全局变量作为循环条件时)然后您会感到惊讶并且很难检测到错误......
    • @KasigiYabu - 完全正确。这通常也是我的标准方法。
    猜你喜欢
    • 2021-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-01
    • 1970-01-01
    • 2021-11-24
    • 2012-11-16
    • 1970-01-01
    相关资源
    最近更新 更多