当前位置:文档之家› Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)

Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)

介绍:什么是线程,线程的优点是什么线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可以看作是Unix进程的表亲,同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。

但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread­local storage)。

一个进程可以有很多线程,每条线程并行执行不同的任务。

线程可以提高应用程序在多核环境下处理诸如文件I/O或者socket I/O等会产生堵塞的情况的表现性能。

在Unix系统中,一个进程包含很多东西,包括可执行程序以及一大堆的诸如文件描述符地址空间等资源。

在很多情况下,完成相关任务的不同代码间需要交换数据。

如果采用多进程的方式,那么通信就需要在用户空间和内核空间进行频繁的切换,开销很大。

但是如果使用多线程的方式,因为可以使用共享的全局变量,所以线程间的通信(数据交换)变得非常高效。

Hello World(线程创建、结束、等待)创建线程 pthread_create线程创建函数包含四个变量,分别为: 1. 一个线程变量名,被创建线程的标识 2. 线程的属性指针,缺省为NULL即可 3. 被创建线程的程序代码 4. 程序代码的参数 For example: ­ pthread_t thrd1; ­pthread_attr_t attr; ­ void thread_function(void argument); ­ char *some_argument;pthread_create(&thrd1, NULL, (void *)&thread_function, (void *) &some_argument);结束线程 pthread_exit线程结束调用实例:pthread_exit(void *retval); //retval用于存放线程结束的退出状态线程等待 pthread_joinpthread_create调用成功以后,新线程和老线程谁先执行,谁后执行用户是不知道的,这一块取决与操作系统对线程的调度,如果我们需要等待指定线程结束,需要使用pthread_join函数,这个函数实际上类似与多进程编程中的waitpid。

举个例子,以下假设 A 线程调用 pthread_join 试图去操作B线程,该函数将A线程阻塞,直到B线程退出,当B线程退出以后,A线程会收集B线程的返回码。

该函数包含两个参数:pthread_t th //th是要等待结束的线程的标识void **thread_return //指针thread_return指向的位置存放的是终止线程的返回状态。

调用实例:pthread_join(thrd1, NULL);example1:1 /*************************************************************************2 > F i l e N a m e: t h r e a d_h e l l o_w o r l d.c3 > A u t h o r: c o u l d t t(f y b y)4 > M a i l: f u y u n b i y i@g m a i l.c o m5 > C r e a t e d T i m e: 2013年12月14日 星期六 11时48分50秒6 ************************************************************************/78 #i n c l u d e <s t d i o.h>9 #i n c l u d e <s t d l i b.h>10 #i n c l u d e <p t h r e a d.h>1112 v o i d p r i n t_m e s s a g e_f u n c t i o n (v o i d *p t r);1314 i n t m a i n()15 {16 i n t t m p1, t m p2;17 v o i d *r e t v a l;18 p t h r e a d_t t h r e a d1, t h r e a d2;19 c h a r *m e s s a g e1 = "t h r e a d1";20 c h a r *m e s s a g e2 = "t h r e a d2";2122 i n t r e t_t h r d1, r e t_t h r d2;2324 r e t_t h r d1 = p t h r e a d_c r e a t e(&t h r e a d1, N U L L, (v o i d *)&p r i n t_m e s s a g e_f u n c t i o n, (v o i d *) m e s s a g e1);25 r e t_t h r d2 = p t h r e a d_c r e a t e(&t h r e a d2, N U L L, (v o i d *)&p r i n t_m e s s a g e_f u n c t i o n, (v o i d *) m e s s a g e2);2627 // 线程创建成功,返回0,失败返回失败号28 i f (r e t_t h r d1 != 0) {29 p r i n t f("线程1创建失败\n");30 } e l s e {31 p r i n t f("线程1创建成功\n");32 }3334 i f (r e t_t h r d2 != 0) {35 p r i n t f("线程2创建失败\n");36 } e l s e {37 p r i n t f("线程2创建成功\n");38 }3940 //同样,p t h r e a d_j o i n的返回值成功为041 t m p1 = p t h r e a d_j o i n(t h r e a d1, &r e t v a l);42 p r i n t f("t h r e a d1 r e t u r n v a l u e(r e t v a l) i s %d\n", (i n t)r e t v a l);43 p r i n t f("t h r e a d1 r e t u r n v a l u e(t m p) i s %d\n", t m p1);44 i f (t m p1 != 0) {45 p r i n t f("c a n n o t j o i n w i t h t h r e a d1\n");46 }47 p r i n t f("t h r e a d1 e n d\n");4849 t m p2 = p t h r e a d_j o i n(t h r e a d1, &r e t v a l);50 p r i n t f("t h r e a d2 r e t u r n v a l u e(r e t v a l) i s %d\n", (i n t)r e t v a l);51 p r i n t f("t h r e a d2 r e t u r n v a l u e(t m p) i s %d\n", t m p1);52 i f (t m p2 != 0) {53 p r i n t f("c a n n o t j o i n w i t h t h r e a d2\n");54 }55 p r i n t f("t h r e a d2 e n d\n");5657 }5859 v o i d p r i n t_m e s s a g e_f u n c t i o n( v o i d *p t r ) {60 i n t i = 0;61 f o r (i; i<5; i++) {62 p r i n t f("%s:%d\n", (c h a r *)p t r, i);63 }64 }编译gcc thread_hello_world.c -otest -lpthread 一定要加上-lpthread,要不然会报错,因为源代码里引用了pthread.h里的东西,所以在gcc进行链接的时候,必须要找到这些库的二进制实现代码。

运行结果结果分析: 1.这段程序我运行了两次,可以看到,两次的运行结果是不一样的,从而说明,新线程和老线程谁先执行,谁后执行用户是不知道的,这一块取决与操作系统对线程的调度。

2.另外,我们看到,在thread2的join结果出现了错误,打印出cannot join with thread2其实这个是个小错误,因为,我pthread_join传进去的th是thread1,在上面的结果中,thread1早已经结束了,所以我们再次等待thread1结束肯定会出现无法取到状态的错误的。

3.pthread_join(thread1, &retval)确实等待了thread1的结束,我们看到,在print_message_function函数循环了5遍结束以后,才打印出thread1 end这是一个非常简单的例子,hello world级别的,只是用来演示Linux下C多线程的使用,在实际应用中,由于多个线程往往会访问共享的资源(典型的是访问同一个全局变量),因此多个县城间存在着竞争的关系,这就需要对多个线程进行同步,对其访问的数据予以保护。

多线程的同步与互斥方式一:锁在主线程中初始化锁为解锁状态pthread_mutex_t mutex;pthread_mutex_init(&mutex, NULL);在编译时初始化锁为解锁状态锁初始化 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;访问对象时的加锁操作与解锁操作加锁 pthread_mutex_lock(&mutex)释放锁 pthread_mutex_unlock(&mutex)不加锁,数据不同步我们先来看一个不加锁,多个线程访问同一段数据的程序。

相关主题