我们在前面曾经说过,当多个互相独立的处理算法对同一个共享的数据结构进行处理的时候使用多线程是有用的。严格地说你也可以使用多个进程(每个进程有一个线程)来共享数据,有些情况下使用同一个进程中的多个线程来处理会更简单些。下面说说在哪里以及为什么要使用多线程。
我们的例子里,我们会使用一个标准的输入/处理/输出的模型。通常来说,这个模型的一部分负责从什么地方获取输入,另外一部分负责处理输入并产生某种形式的输出,第三部分则是将输出反馈到什么地方。
多进程
先来看看多进程、每个进程一个线程的情况。在这里,我们有三个进程,一个输入进程、一个处理进程和一个输出进程,如下面的示意图所示:
阅读全文…
假设我们略微修改我们的例子,让它能演示有些时候在单处理器上使用多线程的好处。
在这个修改的例子里面,网络中的一个节点负责计算扫描线(与前面的图像例子一样)。不过,当一个扫描线的计算结束后,它的数据就通过网络发送到另外一个节点。下面是我们修改后的main()函数:
阅读全文…
前面我们讲过main()函数与工作线程结束进行的同步,在那里提到了两种方式:pthread_join()函数以及壁垒(barrier)。
现在我们回到房子的比喻,假设这个家庭准备到哪个地方旅行。司机上了小货车并发动了引擎。之后,司机就开始等待。只有全部的家庭成员都上车之后,这个小货车才会开动——因为我们不想把任何人落下!
这和我们在前面说的那个绘图程序的原理是一模一样的。主线程要等待全部工作线程结束后,才执行下一步的程序。
不过和这个比喻还有一个很大的差别。那就是通过使用pthread_join()函数,我们是等待所有工作线程的结束。也就是说,之后这些线程已经不存在了,它们退出了。
阅读全文…
任何线程在同一个进程中都可以创建另一个线程,这没有任何的限制。创建线程最常用的就是POSIX函数pthread_create(),该函数的定义如下:
#include <pthread.h>
int
pthread_create (pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine) (void *),
void *arg);
函数pthread_create()有四个参数:
thread 一个指向pthread_t的指针,在那里保存着线程的ID;
阅读全文…
任何线程都能够启动一个进程;唯一的限制就是安全原因的因素,比如文件访问、权限限制等等。实际上,你可以通过系统启动脚本、命令行以及程序调用的方式来启动一个进程。
从命令行启动一个进程
在命令行键入:
$ program1
就会启动一个叫做program1的程序并等待其运行结束。你也可以键入:
$ program2 &
来启动一个叫做program2的程序而不需要等待其运行结束。我们可以称为这个程序在后台运行。
如果你想要在启动一个程序之前先调整这个程序的优先级,你可以使用nice命令,就像在UNIX系统中一样:
$ nice program3
这个指令将在降低的优先级启动这个程序program3。
在程序中启动一个进程
你可能有时会忽略命令行能创建进程,这也是命令行的基本功能。在一些应用程序设计中,可能会用到脚本程序(文件中有批处理指令)来完成某些工作,不过在其他情况下,你需要在程序中自己创建进程。
例如,在一个大型的多进程系统中,你需要一个主进程按照某种配置来启动其他的进程。另外的例子就是当检测到某些操作条件或事件时启动某个进程。
系统提供的能够启动其他进程的函数包括了:
- system()
- exec()
- spawn()
- fork()
- vfork()
你要使用哪个函数取决于两个因素:可移植性与功能性。一般来说,要在这两个因素之间寻找最佳的平衡。
阅读全文…
近期评论