初识Linux多线程编程

来源:互联网 发布:2016淘宝网红店铺排名 编辑:程序博客网 时间:2024/06/09 17:47

本文主要参考http://www.cnblogs.com/skynet/archive/2010/10/30/1865267.html

一个看起来简单而实际涉及很多细节的关于多线程编程的实例,文章主要以该实例展开讲解,例程如下

是否熟悉POSIX多线程编程技术?如熟悉,编写程序完成如下功能:

1有一int型全局变量g_Flag初始值为0

2在主线称中起动线程1,打印“thisis thread1”,并将g_Flag设置为1

3在主线称中启动线程2,打印“thisis thread2”,并将g_Flag设置为2

4线程序2需要在线程1退出后才能退出

5主线程在检测到g_Flag1变为2,或者从2变为1的时候退出

主要介绍了:

a)        进程与线程;

b)       使用线程的理由;

c)        有关线程操作的函数;

d)       线程之间的互斥;

e)        线程之间的同步;

f)        试题最终代码


编程测试过程遇到的问题:

1)编译过程出现错误:undefined reference to `pthread_create',原因是pthread库不是标准linux库。编译选项应加上- lpthread,若要加入-o选项指定输出文件名,则必须将- lpthread选项置于最后,即gcc (-o target) X.C –lpthread

2)定义了全局变量g_flag = 0,主线程main函数中分别调用了两个子线程thread1,thread2,两个子线程函数中分别修改g_flag的值为1,2。然而,g_flag值改变前的输出总是0,而不是前一个线程修改后的值,也就是说全局变量在两个子线程执行后其值不变。为了验证猜想,在主线程函数main的两个子线程之间加入了语句g_flag= 3,其执行情况如下。


以上,确实表明两个子线程对全局变量g_flag值的修改在退出各自线程后失效了。Why?有这样一种可能,两个线程在打印第一条内容时,均没有其他线程对g_flag进行修改。(不过这就太巧了,两个线程应该严格按照交叉的顺序来执行,但我尝试了多次打印,竟没有一次按预期发生的,这还是巧合吗?很奇怪)

3)为了防止thread1与thread2同时对g_flag进行修改,使用了thread_mutex_lock线程锁对代码临界段进行锁定(这里是修改g_flag值的过程)以禁止其他线程访问同一资源;针对例程第四条需求,在线程thread2退出前使用了pthread_join函数阻塞其退出直至thread1先退出;针对例程第五条需求有使用条件变量可以以原子方式阻塞线程,直到某个特定条件为真为止。条件变量始终与互斥锁一起使用。对条件的测试是在互斥锁(互斥)的保护下进行的”。因此,在主线程main函数中使用了pthread_cond_wait以阻塞主线程main函数退出直至条件变量cond为真,而pthread_cond_signal则用于发出条件变量为真的信号。截取代码的三次运行表现如下:


以上,可以看出程序第一次运行,thread2执行前thread1修改了g_flag的值,然而第二次运行时,thread2执行前thread1并未修改g_flag的值。

此外,这里条件变量为真的判断及pthread_cond_signal信号的发出之所以与thread_mutex_lock互斥锁一起使用,并在互斥锁(互斥)的保护下进行,是因为“某个特性条件”通常是在多个线程之间共享的某个变量。互斥锁允许这个变量可以在不同的线程中设置和检测。

4)对于例程第五条需求,个人认为博客文章中并没有严格实现,我理解的需求应是thread1或是thread2仅有其一可修改g_flag值,然后主线程检测到信号cong为真即退出。文章的实现方式如下:


通过加入else分支,使g_flag仅可被修改一次,


运行结果也很有意思,


从第一次运行情况来看thread2在第一次输出g_flag值时,其值为0;而接下来的if判断时,其值已经同步了thread2对g_flag的修改,g_flag = 1。这样,似乎确实这么巧,也验证了2)中的猜测。

下面是本文测试的最终代码:

#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <errno.h>#include <unistd.h>int g_flag = 0;static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;void *func1(void *);void *func2(void *);int main(int argc, char **argv){    printf("[main] enter\n");    pthread_t tid1, tid2;int rc1 = 0, rc2 = 0;rc1 = pthread_create( &tid1, NULL, func1, NULL );if(0 != rc1){    printf("%s: %d\n", __func__, strerror(rc1));}       //sleep(5);  //单位s    //g_flag = 3;    rc2 = pthread_create( &tid2, NULL, func2, &tid1 );if(0 != rc2){    printf("%s: %d\n", __func__, strerror(rc2));}    pthread_cond_wait( &cond, &mutex );  //阻塞线程直至cond为真printf("[main] leave\n");exit(0);}void *func1(void *arg){    printf("[func1] enter\n");printf("this is thread1, g_flag = %d, t_id:%u\n", g_flag, (unsigned int)pthread_self());    pthread_mutex_lock( &mutex );    if(2 == g_flag){    printf("thread2 has made g_flag = 2\n");pthread_cond_signal( &cond );}else{    g_flag = 1;}pthread_mutex_unlock( &mutex );printf("this is thread1, g_flag = %d, t_id:%u\n", g_flag, (unsigned int)pthread_self());printf("[func1] leave\n");pthread_exit(0);    //exit(0);}void *func2(void *arg){    printf("[func2] enter\n");printf("this is thread2, g_flag = %d, t_id:%u\n", g_flag, (unsigned int)pthread_self());pthread_mutex_lock( &mutex );if(1 == g_flag)    {       printf("thread1 has made g_flag = 1\n");    pthread_cond_signal( &cond );    }else{        g_flag = 2;}    pthread_mutex_unlock( &mutex );printf("this is thread2, g_flag = %d, t_id:%u\n", g_flag, (unsigned int)pthread_self());pthread_join( *(pthread_t *)arg, NULL );printf("[func2] leave\n");pthread_exit(0);    //exit(0);}

由于初次接触多线程编程,文中难免会有理解不到位的地方


原创粉丝点击