分享
 
 
 

POSIX线程编程起步(1)-Hello World

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

前言

在UNIX主机上,线程常常又被称为“轻量级进程”,这种称呼很简单同时也便于理解,事实上,UNIX线程是从进程演变而来的。与进程相比,线程相当小,创建线程引起的CPU开销也相对较小。不仅如此,由于线程可以共享内存资源,而不像进程那样拥有独立的内存空间,所以使用线程也很节省内存。以后的几篇文章,将重点讲述POSIX 线程标准最常用的部分(主要基于其在DEC OSF/1 OS, V3.0上的实现)。

1.Hello World

创建进程所用的函数是pthread_create()。它的四个参数包括了:一个线程(pthread_t)变量的指针、一个线程属性(pthread_attr_t)变量的指针、线程启动时所要运行的函数指针以及传递给该函数的一个参数(void *)。

pthread_t a_thread;

pthread_attr_t a_thread_attribute;

void * thread_function(void *argument);

char *some_argument;

pthread_create( &a_thread, a_thread_attribute, thread_function, (void *)some_argument);

很多时候,线程属性变量仅仅指定线程使用的最小栈。其实它有更丰富的含义,但现在的情况是,大多数应用程序创建新线程时值不过传递了一个PTHREAD_ATTR_DEFAULT,有时甚至只是NULL。用pthread_create()创建出的新线程,从指定的函数入口开始执行,这与创建进程不同:所有的进程都具有相同的执行序列。这样设计的原因很简单:如果所有的进程都从同一进程空间的同一处开始执行,那么就会有多个进程对相同的共享资源执行相同的指令。

现在我们已经知道如何创建新线程,就让我们来开始第一个多线程程序:用多个线程在屏幕上输出“Hello World”。为了显示线程的作用,我们将用到两个线程:一个用来输出“Hello”、另一个用来输出“World”。为此,我们首先需要一个用于屏幕输出的函数,新线程将从此函数开始执行。此外,我们还需要两个线程(pthread_t)变量,用来创建新线程。当然,我们需要在pthread_create()的参数中指明每个新线程应该输出的字符串。请看以下代码:

void * print_message_function( void *ptr );

main()

{

pthread_t thread1, thread2;

char *message1 = "Hello";

char *message2 = "World";

pthread_create( &thread1, pthread_attr_default,

print_message_function, (void*) message1);

pthread_create(&thread2, pthread_attr_default,

print_message_function, (void*) message2);

exit(0);

}

void * print_message_function( void *ptr )

{

char *message;

message = (char *) ptr;

printf("%s ", message);

}

这里需要注意的是print_message_function()函数的原型,以及创建新线程时对参数类型的转换。程序首先创建第一个新线程并将“Hello”作为参数传递,接着创建了另一个线程并传递“World”作为起始参数。我们希望第一个线程从printf_message_function()开始执行,在输出“Hello”后结束,接着第二个线程在输出“World”之后也同样地结束。这样的过程看起来似乎很合理,然而其中有两处严重缺陷。

首先,不同的线程是并行运行的,并无先后次序。因此我们无法保证第一个新线程在第二线程之前输出字符串。其结果是,屏幕输出可能是“Hello World”,也可能是“World Hello”。其次,与上述原因类似,父线程(姑且如此称呼)有可能在两个子线程输出之前就执行了exit(0),这将导致整个进程结束——当然两个子进程也就因此而结束了。其后果是屏幕上可能根本没有输出。为了解决第二个问题,我们可以用pthread_exit()来代替exit(),这样两个子进程就不会结束(因为该函数不会终止整个进程的运行)。

目前我们的小程序有两个竞争条件,现在让我们试着用比较笨的办法来解决它们。首先,为了让两个子线程按照我们需要的顺序运行,我们在创建第二个线程之前插入一个延迟。接着,为了保证在子线程结束之前父线程不退出,我们在父线程的尾部也插入一个延迟。请看下面的代码:

void * print_message_function( void *ptr );

main()

{

pthread_t thread1, thread2;

char *message1 = "Hello";

char *message2 = "World";

pthread_create( &thread1, pthread_attr_default,

print_message_function, (void *) message1);

sleep(10);

pthread_create(&thread2, pthread_attr_default,

print_message_function, (void *) message2);

sleep(10);

exit(0);

}

void * print_message_function( void *ptr )

{

char *message;

message = (char *) ptr;

printf("%s", message);

pthread_exit(0);

}

令人遗憾的是,以上代码仍然不能达到我们的目的。利用延迟来进行线程同步是很不可靠的。我们目前遇到的同步问题本质上与分布式程序设计中的同步问题相同:我们永远无法确知某一个线程将会在何时结束。

以上代码的缺陷不只是不可靠,事实上sleep()函数执行时,整个进程都在睡觉而不仅仅是父线程,这一点和exit()很像。当sleep()返回时,我们的程序仍然面对着相同的条件竞争。我们的新代码不仅没有解决竞争问题,反而让我们多花了20秒来等待程序结束。顺便应该指出,如果想要对某一线程进行延迟,应该调用pthread_delay_np()函数(np意指non portable,不可移植),如下:

struct timespec delay;

delay.tv_sec = 2;

delay.tv_nsec = 0;

pthread_delay_np( &delay );

本节涉及的函数:

pthread_create(), pthread_exit(), pthread_delay_np().

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有