日历

« 2008-07-24  
  12345
6789101112
13141516171819
20212223242526
2728293031  

RSS订阅

我是一匹静静奔跑的骏马\r\n ~~~~~~~~~~~~~~~~~~~\r\n in doing we learn!\r\n ~~~~~~~~~~~~~~~~~~~\r\n

posix多线程学习总结

2007-08-23 10:43:10

    最经一段时间一直在做linux下的多线程程序,空余之际对自己做以下总结

Posix多线程学习总结

线程与进程

线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
5zyL;p_?^0   
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.LUPA开源社区&cF~GKaP
   
线程是进程的一个实体,CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源
.LUPA开源社区:T6Jt9b},}D
   
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.

 

创建线程

* pthread_create *
"@v,ue%B0int pthread_create(pthread_t *tid, const pthread_attr_t *tattr, void *(*start_routine)(void *), void *arg);LUPA开源社区"gF/b}t?/r
返回值:函数成功返回0。任何其他返回值都表示错误。创建一个线程参数tattr中含有初始化线程所需要的属性,
)Qf]B9Ry;P3Y5~0start_routine
是线程入口函数的地址,当start_routine返回时,相应的线程就结束了。当函数成功时,线程标示符保存在参数tid指向的内存中。

void receive_func( int *socketid )
"hIJwv$GX*R0{LUPA开源社区1l&LyV9|/d
    /*  线程ID       */LUPA开源社区(y e+f+U3unb
    pthread_t sendptid = 0;
|x g5E+rb3V-{0    pthread_t receiveptid = 0;

    int state = 0;LUPA开源社区9v B]*n2GI
   
5~/g/tb)I]0    /*  创建接收线程  */ LUPA开源社区.JXl T7u"Q
    state = pthread_create(&receiveptid, NULL, (void*)&pthread_receive, socketid);
/i_ F l*ZF&m}0\0    if (state != 0)LUPA开源社区9p0O3|!T:r3oS
    {LUPA开源社区nu B/h;N0SWyQ
        fprintf(fpOutput, "create receivepthread error!\n");LUPA开源社区*p2hhf@j_ T ~ g
    }
8C|n9b0kg%z0    /*  创建发送线程  */LUPA开源社区s%[P7u:[yr
    state = pthread_create(&sendptid, NULL, (void*)&pthread_send, socketid);
[3_1K~Kp%P4g0    if (state != 0)
8Wws@Y%b7z0    {
4M${y9SK+G-O0        fprintf(fpOutput,"create sendpthread error!\n");LUPA开源社区&G3a9A#A0[glF
    }

    /*  等待接收线程结束  */
'cfZj S7J0    state = pthread_join(receiveptid, NULL );   
%H6lr0FJ/{0    if(state != 0)
IRe+T4?0    {LUPA开源社区)|f#@!T@h
        fprintf(fpOutput,"join receivepthread error!\n");
S1V-{;WOn0    }LUPA开源社区5[ ODW*R0]t
    printf("receive pthread is end!\n");
+q/om r.Ew8D0    /*  等待发送线程结束  */
gA$k _yx UP0    state = pthread_join(sendptid, NULL );LUPA开源社区9b#vX9Qr1g
    if(state != 0)LUPA开源社区6R!Ig4c T{9~(l@
    {LUPA开源社区Gw0Kn0b[h
        fprintf(fpOutput,"join sendpthread error!\n");LUPA开源社区.o8V5R]Zr6T
    }LUPA开源社区3GQ uhMF`0SY
    printf("send pthread is end!\n");
]V n:\|2|Sk5t0     LUPA开源社区]8U2S7wM*q g c5d
    fprintf(fpOutput,"receive_func end!\n");

    return;

}

pthread_create()中的attrdetchstate可以设置线程属性LUPA开源社区+T Bn)^"f'LGj
(PTHREAD_CREATE_JOINABLE)
m8OdY%|%m'N0
可汇合线程: 终止后还会保留某些分配给它的资源,直到其它线程使用phread_join调用后才能再次分配这些资源.
0X+l.zu-S0(PTHREAD_CREATE_DETACHED)LUPA开源社区)t,E G FqJWa3r
脱离线程:终止时释放该线程的所有资源.其它线程不能用pthread_join来与它的终止进行同步

只要设成了(PTHREAD_CREATE_DETACHED)状态就不能恢复到(PTHREAD_CREATE_JOINABLE)状态LUPA开源社区nA;d kl-u!I.Y
****************************************************

分离线程
C0Tb `h-IbR_:C y0** pthread_detach **
)Ji {} t(yu)_0
分离线程pthread_detach
oQ W u$h0#include <pthread.h>
1N lt.o$r2Oh0int pthread_detach(pthread_t tid);
:V9]?[2M0
返回值:函数成功返回0。任何其他返回值都表示错误。
[I4rE KxB0
将线程设置为脱离线程。即通知线程库在指定的线程终止时回收线程占用的内存等资源。LUPA开源社区!Fk:f/L3u lE9jo
在一个线程上使用多次pthread_detach的结果是不可预见的。LUPA开源社区E0h9QX celR
****************************************************

待线程结束LUPA开源社区#qU'G.HX?;vs~
*** pthread_join   ***
'G[g'wYxd0
待线程结束pthread_join

int pthread_join(pthread_t tid, void **status);
_LrVd#CQ0
返回值:函数成功返回0。任何其他返回值都表示错误。
K4s { _:V9Q!p(f0
等待一个线程结束。
2Q'F{ s-eWY0
调用pthread_join的线程将被挂起.直到参数tid指定的线程结束。
Q:Lo8{#s$FH$mY#t0tid
指定的线程必须在当前进程中,同时tid指定的线程必须是汇合的。
$|x5C#L*Dp0
不能有多个线程等待同一个线程终止。如果出现这种情况,一个线程将成功返回,别的线程将返回错误ESRCH
h2C(E If0
如果参数status不为NULL,则将线程的退出状态放在status指向的内存中。LUPA开源社区&|&]6?9J&\&f
(
用于存放线程所等待的返回值)

int pthread_exit(void *retval)LUPA开源社区5P c"[Uu]U2vTVJ
如果pthread_join()第二个参数不是NULL,那么值就传给status.

/*pthread_joinstatus用于存放等待线程的返回值
)z:js%ESk4\ht0
主要用于看看返回值的测试结果*/

**************************************************** 

比较线程LUPA开源社区8d(xyKKt)T
*** pthread_equal   ***
r/[#uE:f5@/\0
比较线程

int pthread_equal(pthread_t tid1, pthread_t tid2);LUPA开源社区f%q(^_:h k2A
如果tid1tid2相同,函数返回一个非0值,否则返回0
mjvYc"V-X%qI&Q0
如果tid1tid2中任何一个是非法值,则返回将是不可预料的。LUPA开源社区vq:gI L
****************************************************


O/] { PU3n)P3]6M0***pthread_testcancel  ****LUPA开源社区 nzr T NJ+x T:zu
取消线程
G"Ae-b(S2B\Zh0pthread_testcancel();

首先,Cancelation-point并不能单纯的理解成一个,可以理解成一个时间段。posix规定:LUPA开源社区!e1zuH lZ"j
read
函数应该是一个Cancelation-point,就是说:从read开始执行到read返回,当前线程都可以执行Cancelation操作。当前线程可能在read之前就收到了cancel信号,也可能在read的执行过程中收到了cancel信号。linux不支持read等函数成为一个Cancelation-point,为了我们在linux下开发的代码可以满足posix标准,做如下处理:
(L#fNyeFZ1m?us0pthread_testcancel(); LUPA开源社区 v*hv2~!w
retcode = read(fd, buffer, length);
K P]vLG m"A0pthread_testcancel();
3S;Qg}9p|*dS/y0
前面一个pthread_testcancel是为了响应当前线程在read之前收到的cancel信号,后面一个pthread_testcancel是为了响应当前线程在read的执行过程中收到的cancel信号(cancel信号使得线程从阻塞的系统调用read中退出),这样我们就实现了posix标准的要求。

如果线程处于无限循环等待中.且循环体内没有执行至取消点的必然路径.则线程就无法由外部其它线程的取消请求而终止.这样在循环体的必然路径上应加上pthread_testcancel();
U `4Sy9l DX%c0U+l0*****************************************************


]J?jhb7j}H0**** pthread_cancel    ***
4JE H5}8lTip0int pthread_cancel(pthread_t thread)
w}a3wr CC0发送终止信号给thread线程,如果成功则返回0,否则为非0值。发送成功并不意
1d0m/gL0bZE$F4v#?0
味着thread会终止。
2`2t7|~tCJ0****************************************************
 

***** pthread_setcancelstate ****LUPA开源社区*s3K&F-M gerw
int pthread_setcancelstate(int state, int *oldstate)

设置本线程对Cancel信号的反应,state有两种值:PTHREAD_CANCEL_ENABLE(缺省)LUPA开源社区"IYk_ Hk;b5n
PTHREAD_CANCEL_DISABLE,分别表示收到信号后设为CANCLED状态和忽略CANCEL信号继续运行;old_state如果不为NULL则存入原来的Cancel状态以便恢复。 LUPA开源社区2z2VH5i| [#P|#U
****************************************************


%e Q cLo0s8O0**** pthread_setcanceltype   *****LUPA开源社区-RKzq8m%@
int pthread_setcanceltype(int type, int *oldtype)

设置本线程取消动作的执行时机,type由两种取值:PTHREAD_CANCEL_DEFFEREDLUPA开源社区*eOiI-YE3F4~/K
PTHREAD_CANCEL_ASYCHRONOUS
,仅当Cancel状态为Enable时有效,分别表示收到信号后继续运行至下一个取消点再退出和立即执行取消动作(退出);oldtype如果不为NULL则存入运来的取消动作类型值。

 


TAG:

我来说两句

-5 -3 -1 - +1 +3 +5

Open Toolbar