Linux pthread 编程
Linux下线程级编程并不是很复杂,但是不容易使用。最主要的原因是编程人员对于Linux系统自身的线程机制理解的不是很深刻,在这种情况下去使用线程那么许多“看不到”的事情就会降临,自然线程的编写者是看不到这些的。所以线程看起来比较简单,实则,是需要经过精心修炼才能运用自如的。下面是我个人在学习线程编程过程中积累的一点经验,记录如下:
什么是线程?
Window下线程的概念应该已经很成熟,那么Linux的线程是不是跟windows一样呢?我们不必深究其中的细节,它们的共同目标就是让一个进程能够更快的执行自己的代码,更高效的工作。这就是说如果有一个任务,你不想用多进程实现,但又希望它工作的很快,你可以选择多线程。至于多线程跟多进程,哪个更好,在此我不讲述,有兴趣的自己学习相关的资料吧。
线程的创建方法
我们知道进程的创建需要fork来完成。那么,线程也差不多需要调用系统调用来产生新的线程。linux下就是pthread_create()这个API,只要将必要的参数初始化就可以产生一个新的线程执行自己的代码。
首先,介绍一下线程所需要的头文件pthread.h。包含了这个头文件以后,我们就可以使用线程相关的API以及数据结构了(注意:包含头文件的同时,编译的时候要加上-lpthread告诉编译器线lib的位置)。
下面,介绍线程相关的数据结构和API:
pthread_t是一个表示线程类型的数据结构,只要有一个线程就存在一个这样的标识符。它是在创建线程的时候必须指定的,跟进程标识符很相似。
pthread_create()这个API是创建线程的一个API,所有关于新线程的设置都要在这里指定。因此,它的参数比较复杂,我们一个一个看。
练习的code:
int thx = 10;
int thy = 100;
sem_t sem;
void* thread_print(void* parameter){
unsigned int i = *((unsigned int*)parameter);
while(i--){
sem_wait(&sem);
fprintf(stderr, "in thread_print!\n");
}
return (void*)(thx);
}
void* thread_print0(void* parameter){
unsigned int i = *((unsigned int*)parameter);
while(i--){
sem_wait(&sem);
fprintf(stderr, "in thread_print 00000!\n");
}
return (void*)(thy);
}
cout<<"Pthread programming test!"<
pthread_t thread_id;
pthread_t thread_id0;
sem_init(&sem, 0 , 200);
int thread_data = 100;
int thread_data0 = 100;
int res, res0;
int* pres = & res;
int* pres0 = & res0;
pthread_create(&thread_id, NULL, &thread_print, &thread_data);
pthread_create(&thread_id0, NULL, &thread_print0, &thread_data0);
pthread_join(thread_id, (void**)(&(res)));
pthread_join(thread_id0, (void**)&(res0));
cout<<"thread res is "<
值得注意的一个问题
有许多人认为在局部域里面声明的pthread_mutex_t类型的变量,也局部的,这种想法是错误的,原因在于,在Linux的环境下,我们声明pthread_mutex_t类型的变量其实已经默认是一个static的而且在kernel空间范围的一个结构,就是说别的进程以及线程其实也是
关于STL的线程安全问题(转)
tl线程安全的概念是:
多个线程同时读是安全的。a线程创建容器,可以安全的在其他线程读写。
但是,线程安全不包括互斥的语意,因此,多个线程同时修改容器的话,必须互斥。
STL标准是没有规定 必须是线程安全的。
所以 PJ STL(VC++)的STL是非线程安全的,需要用户自己保证线程安全;
而SGI STL(G++)的STL是线程安全的,不需要用户自己保证线程安全。
在所有的主流STL实现方案中,几乎所有的容器都是线程安全的:
1).一个线程读写一个实例时,另一个线程可以读写另一个实例。
2).多个线程可以在同时读同一个container。
3).多个线程读写同一个container时,你应该负责安排互斥性操作。
《Effective STL》
条款12:对STL容器线程安全性的期待现实一些
标准C++的世界是相当保守和陈旧的。在这个纯洁的世界,所有可执行文件都是静态链接的。不存在内存映射文件和共享内存。没有窗口系统,没有网络,没有数
据库,没有其他进程。在这种情况下,当发现标准没有提到任何关于线程的东西时你不该感到惊讶。你对STL的线程安全有的第一个想法应该是它将因实现而不
同。
当然,多线程程序是很普遍的,所以大部分STL厂商努力使他们的实现在线程环境中可以正常工作。但是,即使他们做得很好,大部分负担仍在你肩上,而理解为什么会这样是很重要的。STL厂商只能为你做一些可以减少你多线程的痛苦的事情,你需要知道他们做了什么。
在STL容器(和大多数厂商的愿望)里对多线程支持的黄金规则已经由SGI定义,并且在它们的STL网站[21]上发布。大体上说,你能从实现里确定的最多是下列内容:
多个读取者是安全的。多线程可能同时读取一个容器的内容,这将正确地执行。当然,在读取时不能有任何写入者操作这个容器。
对不同容器的多个写入者是安全的。多线程可以同时写不同的容器。
就这些了,那么让我解释你可以期望的是什么,而不是你可以确定的。有些实现提供这些保证,但是有些不。
写多线程的代码很难,很多程序员希望STL实现是完全线程安全的。如果是那样,程序员可以不再需要自己做并行控制。毫无疑问这将带来很多方便,但这也非常难实现。一个库可能试图以下列方式实现这样完全线程安全的容器:
在每次调用容器的成员函数期间都要锁定该容器。
在每个容器返回的迭代器(例如通过调用begin或end)的生存期之内都要锁定该容器。
在每个在容器上调用的算法执行期间锁定该容器。(这事实上没有意义,因为,正如条款32所解释的,算法没有办法识别出它们正在操作的容器。不过,我们将在这里检验这个选项,因为它的教育意义在于看看为什么即使是可能的它也不能工作。)
阅读(2107) | 评论(0) | 转发(0) |