设为首页 加入收藏

TOP

11.3.2 CRT改进
2013-10-07 00:44:41 来源: 作者: 【 】 浏览:59
Tags:11.3.2 CRT 改进

11.3.2  CRT改进

使用TLS

多线程运行库具有什么样的改进呢?首先,errno必须成为各个线程的私有成员。在glibc中,errno被定义为一个宏,如下:

#define errno (*__errno_location ())

函数__errno_location在不同的库版本下有不同的定义,在单线程版本中,它仅直接返回了全局变量errno的地址。而在多线程版本中,不同线程调用__errno_location返回的地址则各不相同。在MSVC中,errno同样是一个宏,其实现方式和glibc类似。

加锁

在多线程版本的运行库中,线程不安全的函数内部都会自动地进行加锁,包括malloc、printf等,而异常处理的错误也早早就解决了。因此使用多线程版本的运行库时,即使在malloc/new前后不进行加锁,也不会出现并发冲突。

改进函数调用方式

C语言的运行库为了支持多线程特性,必须做出一些改进。一种改进的办法就是修改所有的线程不安全的函数的参数列表,改成某种线程安全的版本。比如MSVC的CRT就提供了线程安全版本的strtok()函数:strtok_s,它们的原型如下:

char *strtok(char *strToken, const char *strDelimit );
char *strtok_s( char *strToken, const char *strDelimit, char **context);

改进后的strtok_s增加了一个参数,这个参数context是由调用者提供一个char*指针,strtok_s将每次调用后的字符串位置保存在这个指针中。而之前版本的strtok函数会将这个位置保存在一个函数内部的静态局部变量中,如果有多个线程同时调用这个函数,有可能出现冲突。与MSVC CRT类似,Glibc也提供了一个线程安全版本的strtok()叫做strtok_r()。

但是很多时候改变标准库函数的做法是不可行的。标准库之所以称之为"标准",就是它具有一定的权威性和稳定性,不能随意更改。如果随意更改,那么所有遵循该标准的程序都需要重新进行修改,这个"标准"是不是值得遵循就有待商榷了。所以更好的做法是不改变任何标准库函数的原型,只是对标准库的实现进行一些改进,使得它能够在多线程的环境下也能够顺利运行,做到向后兼容。

【责任编辑:云霞 TEL:(010)68476606】

回书目   上一节   下一节

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇11.3.3 线程局部存储实现(1) 下一篇11.4.2 MSVC CRT的全局构造和析构..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: