COMMENTS

Linux多线程(1)

学习参考《linux高级程序设计卷一》

GNU/Linux 实现了 POSIX 标准线程 API。所有线程函数和数据类型都在<pthread.h>头文件中声明。这些线程相关的函数没有被包含在 C 标准库中,而是在libpthread 中,所以当链接程序的时候需在命令行中加入 -lpthread 以确保能正确链接。

1.创建线程

创建线程使用pthread_create函数,函数原型:

int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(*start_routine)(void *),void *arg)

参数解释:
a.一个指向pthread_t 类型变量的指针,新线程的线程 ID 将存储在这里。
b.一个指向线程属性(thread attribute)对象的指针,这个对象控制着新线程与程序其它部分交互的具体细节。如果传递NULL 作为线程属性,新线程将被赋予一组默认线程属性。
c.一个指向线程函数的指针。这是一个普通的函数指针,类型如下:void* (*) (void*)。
d.一个线程参数,类型void*,不论你传递什么值作为这个参数,当线程开始执行的时候,它都会被直接传递给新的线程。

函数 pthread_create 会在调用后立刻返回,原线程会继续执行之后的指令。同时,新线程开始执行线程函数。Linux 异步调度这两个线程,因此你的程序不能依赖两个线程得到执行的特定先后顺序。

1.1线程参数传递

pthread_create的第四个参数为第三个参数(线程将要执行的函数)的参数,通常的做法是给线程函数定义一个结构以包含线程函数所期待的实际参数序列,给线程函数定义一个结构以包含线程函数所期待的实际参数序列。

1.2等待线程

因为线程共享了主线程的数据,尤其是当给线程传递了参数时,主线程必须等待线程执行完成后才可以退出,严格的说主线程必须在线程执行完成之前确保参数的完整,因为通常这些参数是在主线程中定义的。这类似于局部变量(当生命期结束的时候自动释放)和堆上分配的对象(通过free或者C++的delete手工释放)。务必确保这个变量不会被释放(甚至在其它线程中也不行!),直到你确定这个线程不会再使用它。
使用pthread_join(pthread_t thread,void **retval),强制主线程等待线程退出。

一个例子–主线程创建两个线程,一个输出x,另一个输出o。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <stdio.h> 
#include <pthread.h>
 
/* print_function 的参数 */
struct char_print_parms
{
/* 用于输出的字符 */
char character;
/* 输出的次数 */
int count;
};
/* 按照 PARAMETERS 提供的数据,输出一定数量的字符到stderr。
PARAMETERS 是一个指向 struct char_print_parms 的指针 */
void* char_print (void* parameters)
{
/* 将参数指针转换为正确的类型 */
struct char_print_parms* p = (struct char_print_parms*) parameters;
int i;
for (i = 0; i &lt; p-&gt;count; ++i)
fputc (p-&gt;character, stderr);
return NULL;
}
/* 主程序 */
 
int main ()
{
pthread_t thread1_id;
pthread_t thread2_id;
struct char_print_parms thread1_args;
struct char_print_parms thread2_args;
/* 创建一个输出 30000 个 x 的线程 */
hread1_args.character = 'x';
thread1_args.count = 30000;
prhread_create (&amp;thread1_id, NULL, &amp;char_print, &amp;thread1_args);
 
/* 创建一个输出 20000 个 o 的线程 */
thread2_args.character = 'o';
thread2_args.count = 20000;
pthread_create (&amp;thread2_id, NULL, &amp;char_print, &amp;thread2_args);
/* 确保第一个线程结束 */
pthread_join (thread1_id, NULL);
/* 确保第二个线程结束 */
pthread_join (thread2_id, NULL);
/* 现在我们可以安全地返回 */
return 0;
}

1.3 线程取消

在一个线程中以另一个线程ID作为参数调用pthread_cancel可以取消另一个线程。但是,线程可能运行在一段不可分割的代码中,必须全部得到执行或者干脆不执行。例如,线程可能分配一些资源,使用并稍后释放它们。如果线程在中途被取消,它可能没有机会释放那些被分配的资源,从而导致资源的泄漏。为防止这种情况发生,一个线程可以控制自身是否可以被取消,以及何时允许取消操作。

线程可以调用pthread_setcancelstate和pthread_setcanceltype来决定自身是否允许被其他线程取消,及取消方式(PTHREAD_CANCEL_DEFERRED和PTHREAD_CANCEL_ASYNCHRONOUS)。

相关文章:
  1. C hash table code
  2. 使用原始套接字SOCK_RAW捕捉网络数据包并简单分析
  3. MD5应用的一点理解及Linux实现源码
  4. 使用setitimer和signal创建一个计时器
  5. 自写一则单链表小程序

1 comment to Linux多线程(1)

Leave a Reply

 

 

 

:wink: :twisted: :roll: :oops: :mrgreen: :lol: :idea: :evil: :cry: :arrow: :?: :-| :-x :-o :-P :-D :-? :) :( :!: 8-O 8)