POSIX多线程—异步编程举例

Content

0.序

1.基本的同步版本

2.多进程版本

3.多线程版本

4.小结


0.序

本节通过一个简单的闹钟实例演示异步编程方法。

该程序循环接受用户输入信息,直到出错或者输入完毕。用户输入的每行信息有两部分:闹钟等待的时间(秒)和闹钟时间到达时显示的文本信息。

1.基本的同步版本

代码如下。


POSIX多线程—异步编程举例_第1张图片

特点:同步实现异步,闹钟请求后,程序睡眠等待闹钟时间到;

问题:用同步方式来实现异步,致一次只能处理一个闹钟请求;即程序睡眠时间到后才能进行下一次闹钟请求;

运行结果。

POSIX多线程—异步编程举例_第2张图片

2.多进程版本

代码如下。

POSIX多线程—异步编程举例_第3张图片
POSIX多线程—异步编程举例_第4张图片

特点:在子进程中异步地调用sleep函数,而父进程继续运行;

问题:对每次闹钟请求,使用fork创建子进程,程序开销过大;

waitpid()函数

WNOHANG:父进程不必挂起等待子进程的结束;

如果有子进程终止,该函数回收该子进程的资源;

如果没有子进程终止,该函数立即返回pid=0;父进程继续回收终止的子进程直到没有子进程终止;

在每个命令之后循环调用waitpid,来回收所有结束的子进程;

运行结果。

POSIX多线程—异步编程举例_第5张图片

3.多线程版本

代码如下。

POSIX多线程—异步编程举例_第6张图片
POSIX多线程—异步编程举例_第7张图片

特点:在该例子中,alarm线程调用pthread_detach()函数来分离自己,通知pthreads不必关心它的终止时间和退出状态;因此不需要等待线程结束,除非希望获得它的返回值。alarm线程的资源在它终止后立即回收。

一般地,pthreads会保存线程的资源以使其他线程了解它已经终止并获得其最终结果。在本例中,alarm线程负责自己分离自己。

该版本用到以下函数:

pthread_create():创建线程,运行代码由第三个参数指定,运行代码需要的参数由第四个参数传入;返回线程标志符;

Pthread_detach():当线程终止时允许pthreads立即回收线程资源;

pthread_exit():终止调用线程;

运行结果。

POSIX多线程—异步编程举例_第8张图片

4.小结

多进程版本

每个闹钟有一个从主进程拷贝的独立地址空间;

主进程调用waitpid来告诉系统释放其创建的子进程资源;

多线程版本

所有线程共享同一个地址空间;

不需要等待线程结束,除非希望获得它的返回值;

线程间传递消息更快

不需要映射共享内存;

不需要通过管道读写;

不需要担心进程间传送的地址指针是否一致;

线程间共享一切:一个线程内有效的地址指针在所有线程内同样有效;

多线程编程优点

在多处理器系统中开发程序的并行性(仅并行性需要特殊硬件支持);

在等待慢速外设I/O操作结束的同时,程序可以执行其他计算,为程序的并发提供更有效、更自然的开发方式;

一种模块化编程模型,能清晰地表达程序中独立事件间的相互关系;

多线程编程缺点

计算负荷,如线程间同步需要的时间代价;

需要设立较好的编程规则,如要避免死锁、竞争和优先级倒置等;

更难以调试;

何种应用适合使用多线程?

计算密集型应用,为了能在多处理器系统上运行,将这些计算分解到多个线程中实现;

IO密集型应用,为提高性能,将IO操作重叠;如分布式服务器;

Reference

# man waitpid

# man pthread_create

# man pthread_detach

作者:阿波

你可能感兴趣的:(POSIX多线程—异步编程举例)