写关于errno的时候发现了一个问题,errno是全局变量,对于多线程来说是否要加锁呢?
自己下来做了个实验,自己手写全局变量在多线程环境下会乱序。程序如下图。
#include <iostream>
#include <sys/stat.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#include <pthread.h>
#include <errno.h>
using namespace std;
int x = 0;
void *funcA(void *) {
while (1) {
x = 1;
sleep(1);
cout << "A" << x << endl;
}
}
void *funcB(void *) {
while (1) {
x = 2;
sleep(2);
cout << "B" << x << endl;
}
}
int main() {
pthread_t a, b;
pthread_create(&a, NULL, funcA, NULL);
pthread_create(&b, NULL, funcB, NULL);
sleep(10000);
return 0;
}
显然不是线程安全的。但是将全局变量x换成了errno后,发现不会有乱配的现象了。
最后将funcB内赋值函数屏掉。发现B内的errno永远都是0,A内的errno永远都是1。
这个结论证明,线程之间的errno并不是共享的,而是两个不同的变量。
在网上查后,得知errno是使用了TLS技术(thread local storage)。
这个技术保证了全局变量只在单个线程内有一份。做法是在全局变量前加_thread即可。具体操作实现每个平台不同,但原理基本上是将原值复制出来给每个线程各一份,这样线程之间调用全局变量就不会冲突了。当然没有_thread修饰的全局变量还是多线程竞争关系。