CRT的多线程困扰

100 篇文章 0 订阅

线程的访问权限

线程的访问能力非常自由,它可以访问进程内存里的所有数据,甚至包括其他线程的堆栈(如果它知道其他线程的堆栈地址,然而这是很少见的情况),但实际运用中线程也拥有自己的私有存储空间,包括:

栈(尽管并非完全无法被其他线程访问,但一般情况下仍然可以认为是私有的数据)。

线程局部存储(Thread Local Storage, TLS)。线程局部存储是某些操作系统为线程单独提供的私有空间,但通常只具有很有限的尺寸。

寄存器(包括PC寄存器),寄存器是执行流的基本数据,因此为线程私有。

从C程序员的角度来看,数据在线程之间是否私有如表11-3所示。

表11-3

线程私有

线程之间共享(进程所有)

局部变量

函数的参数

TLS数据

全局变量

堆上的数据

函数里的静态变量

程序代码,任何线程都有权利读取并执行任何代码

打开文件,A线程打开的文件可以由B线程读写

多线程运行库

现有版本的C/C++标准(特指C++03、C89、C99)对多线程可以说只字不提,因此相应的C/C++运行库也无法针对线程提供什么帮助,也就是说在运行库里不能找到关于创建、结束、同步线程的函数。对于C/C++标准库来说,线程相关的部分是不属于标准库的内容的,它跟网络、图形图像等一样,属于标准库之外的系统相关库。由于多线程在现代的程序设计中占据非常重要的地位,主流的C运行库在设计时都会考虑到多线程相关的内容。这里我们所说的"多线程相关"主要有两个方面,一方面是提供那些多线程操作的接口,比如创建线程、退出线程、设置线程优先级等函数接口;另外一方面是C运行库本身要能够在多线程的环境下正确运行。

对于第一方面,主流的CRT都会有相应的功能。比如Windows下,MSVC CRT提供了诸如_beginthread()、_endthread()等函数用于线程的创建和退出;而Linux下,glibc也提供了一个可选的线程库pthread(POSIX Thread),它提供了诸如pthread_create()、pthread_exit()等函数用于线程的创建和退出。很明显,这些函数都不属于标准的运行库,它们都是平台相关的。

对于第二个方面,C语言运行库必须支持多线程的环境,这是什么意思呢?实际上,最初CRT在设计的时候是没有考虑多线程环境的,因为当时根本没有多线程这样的概念。到后来多线程在程序中越来越普及,C/C++运行库在多线程环境下吃了不少苦头。例如:

(1)errno:在C标准库里,大多数错误代码是在函数返回之前赋值在名为errno的全局变量里的。多线程并发的时候,有可能A线程的errno的值在获取之前就被B线程给覆盖掉,从而获得错误的出错信息。

(2)strtok()等函数都会使用函数内部的局部静态变量来存储字符串的位置,不同的线程调用这个函数将会把它内部的局部静态变量弄混乱。

(3)malloc/new与free/delete:堆分配/释放函数或关键字在不加锁的情况下是线程不安全的。由于这些函数或关键字的调用十分频繁,因此在保证线程安全的时候显得十分繁琐。

(4)异常处理:在早期的C++运行库里,不同的线程抛出的异常会彼此冲突,从而造成信息丢失的情况。

(5)printf/fprintf及其他IO函数:流输出函数同样是线程不安全的,因为它们共享了同一个控制台或文件输出。不同的输出并发时,信息会混杂在一起。

(6)其他线程不安全函数:包括与信号相关的一些函数。

通常情况下,C标准库中在不进行线程安全保护的情况下自然地具有线程安全的属性的函数有(不考虑errno的因素):

(1)字符处理(ctype.h),包括isdigit、toupper等,这些函数同时还是可重入的。

(2)字符串处理函数(string.h),包括strlen、strcmp等,但其中涉及对参数中的数组进行写入的函数(如strcpy)仅在参数中的数组各不相同时可以并发。

(3)数学函数(math.h),包括sin、pow等,这些函数同时还是可重入的。

(4)字符串转整数/浮点数(stdlib.h),包括atof、atoi、atol、strtod、strtol、strtoul。

(5)获取环境变量(stdlib.h),包括getenv,这个函数同时还是可重入的。

(6)变长数组辅助函数(stdarg.h)。

(7)非局部跳转函数(setjmp.h),包括setjmp和longjmp,前提是longjmp仅跳转到本线程设置的jmpbuf上。

为了解决C标准库在多线程环境下的窘迫处境,许多编译器附带了多线程版本的运行库。在MSVC中,可以用/MT或/MTd等参数指定使用多线程运行库。

 

From:http://book.51cto.com/art/200904/121070.htm

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值