我们应该如何处理系统的全局变量(例如UNIX中的errno)的竞争条件?我查看了Tanenbaum的现代操作系统(第4版,第117页),并说它使用私有全局变量。所以基本上你为全局变量分配了一些内存块,并将它作为参数传递给每个过程。但是如何解决这个问题呢?
答案 0 :(得分:0)
嗯,最好的选择是不使用全局变量。编写可重入函数,使用户传递正确类型的变量(通常在C中它将是一个指向变量的指针)并使用它。例如,请参阅strtok_r()。
如果它是一个你控制的全局变量,因为它在用户代码中并且由于某种原因你无法避免使用它,那就是thread local storage。
如果它是您使用但不能改变的库中的全局,则必须确保使用互斥锁保护它的任何使用。
答案 1 :(得分:0)
正如jww所链接的那样,在大多数多线程感知标准库中,都采取了一些措施来确保系统全局errno
在多线程环境中是理智的。在这个时代,一个没有解决这个问题的图书馆必须被考虑在内,而且没有帮助#34;
在多线程库之前的糟糕时期,对errno
之类的东西产生副作用的标准库函数的调用必须用信号量保护。 Yeurk。
在现代gcc中,扩展__thread:
__thread long myThreadPrivateLong;
其他编译器可能有类似的东西。我偶尔发现这在我自己的代码中很有用。
当然,stdin
,stdout
,stderr
等其他系统全局变量不是线程私有的。这没有任何意义,因为进程只有一个tty
(唉*)。在glibc上,采取了一些措施来确保对stdout
的多线程访问是半理性的,因为像printf()
这样的函数在glibc遇到之后实际输出到stdout
之前通过管道进行缓冲。 EOL。结果是两个线程同时调用printf()
将使它们的输出行分开。在过去,两次调用printf()
所输出的字符只会混杂成一个不可读的混乱。
stderr
未被缓冲。
*我说唉,因为如果有特定于线程的stdouts并且终端应用程序每个线程有一个终端选项卡,那将是非常好的。对用户不是很有用,但有时对开发人员非常有用。能够看到单个线程正在做什么是有用的。