Linux多线程3-2_线程连接

  • Post author:
  • Post category:linux



一、线程连接的作用


int pthread_join(pthead_t tid, void **rval)

1、调用该函数的线程会一直阻塞,直到指定的线程tid调用pthread_exit、从启动例程返回或者被取消

参数tid就是指定线程的id

参数rval是指定线程的返回码,如果线程被取消,那么rval被置为PTHREAD_CANCELED

该函数调用成功会返回0,失败返回错误码

2、调用pthread_join会使指定的线程处于分离状态,如果指定线程已经处于分离状态,那么调用就会失败

pthread_detach可以分离一个线程,线程可以自己分离自己

int pthread_detach(pthread_t thread);

成功返回0,失败返回错误码


二、手册

1、pthread_join()


PTHREAD_JOIN(3)            Linux Programmer’s Manual           PTHREAD_JOIN(3)

NAME

pthread_join – join with a terminated thread


//连接一个正在执行的线程

SYNOPSIS

#include


//包含头文件 pthread.h


int pthread_join(pthread_t thread, void **retval);

Compile and link with -pthread.


//连接线程库

DESCRIPTION

The pthread_join() function waits for the thread specified by thread to terminate.  If that thread has already terminated, then pthread_join() returns         immediately.  The thread  speci-fied by thread must be joinable.






//pthread_join


(pthread_t thread, void **retval);


的作用是等待由thread指定的线程结束,如果那个线程已经结束了,那么这个函数会立即返回。





//这个指定的线程必须是可以连接的

If  retval  is  not  NULL,  then pthread_join() copies the exit status of the target thread(i.e., the value that the target thread supplied pthread_exit(3))        into  the  location pointed  to by *retval.  If the target thread was canceled, then PTHREAD_CANCELED is placed in *retval.


//如果retval不是空,那么线程的返回值就会被充填到这里。如果目标线程已经取消了,那么retval的值就是


PTHREAD_CANCELED


If multiple threads simultaneously try to join with the same thread, the results are  unde-fined.   If  the  thread  calling  pthread_join()  is canceled,         then the target thread will remain joinable (i.e., it will not be detached).


//如果有多个线程连接指定线程,那么结果是未知的。如果调用


pthread_join()的线程被取消了,那么目标线程还是可以连接的


RETURN VALUE

On success, pthread_join() returns 0; on error, it returns an error number.


//成功返回0,失败返回错误码

ERRORS

EDEADLK

A deadlock was detected (e.g., two threads tried to join with each other); or thread specifies the calling thread.


//如果两个线程试图去连接彼此,那么就会导致死锁

EINVAL thread is not a joinable thread.


//线程不是一个可以连接的线程

EINVAL Another thread is already waiting to join with this thread.


//已经有一个线程连接该线程了

ESRCH  No thread with the ID thread could be found.


//目标线程的ID不对

CONFORMING TO

POSIX.1-2001.

NOTES

After  a  successful  call  to  pthread_join(),  the caller is guaranteed that the target thread has terminated.


//如果


pthread_join


()成功返回,那么目标线程已经确定结束了


Joining with a thread that has previously been joined results in undefined behavior.




//如果目标线程已经被连接过,那么结果是未知的

Failure to join with a thread that is joinable (i.e., one that is not detached), produces a “zombie  thread”.   Avoid  doing  this,  since  each  zombie          thread  consumes  some system resources, and when enough zombie threads have accumulated, it will no longer  be  possible to create new         threads (or processes).


//如果连接一个可连接的目标线程失败,那么会导致一个僵尸线程,僵尸线程会占有系统资源,太多的僵尸线程导致无法创建新线程

There  is no pthreads analog of waitpid(-1, &status, 0), that is, “join with any terminated thread”.  If you believe you need this functionality, you probably  need  to  rethink  yourapplication design.


2、pthread_detach

PTHREAD_DETACH(3)          Linux Programmer’s Manual         PTHREAD_DETACH(3)

NAME

pthread_detach – detach a thread

SYNOPSIS

#include


//包含头文件pthread.h

int pthread_detach(pthread_t thread);

Compile and link with -pthread.


//编译和连接线程库

DESCRIPTION

The pthread_detach() function marks the thread identified by thread as detached.  When a detached thread terminates, it resources are automatically released back to the system without the need for another thread to join with the  terminated thread.


//这个函数会导致目标线程变成一个分离的状态,如果一个分离的线程结束了,那么他的资源会被立即回收。

Attempting to detach an already detached thread results in unspecified behavior.




//如果试图去分离一个已经被分离的线程,结果是位置的

RETURN VALUE

On success, pthread_detach() returns 0; on error, it returns an error number.




//成功返回0,失败返回错误码

ERRORS

EINVAL thread is not a joinable thread.




//目标线程是不可连接的

ESRCH  No thread with the ID thread could be found.




//目标线程无法找到

NOTES

Once a thread has been detached, it can’t be joined with pthread_join(3) or be made joinable again.




//一旦一个线程已经被分离了,那么久不能再调用pthread_join()去连接他

A  new  thread  can be created in a detached state using pthread_attr_setdetachstate(3) to set the detached attribute of the attr argument of pthread_create(3).




//在用函数


pthread_create()创建一个线程的时候,可以通过属性把他设置为分离的


The detached attribute merely determines the behavior of the system when the thread terminates; it does not prevent  the thread from being terminated if the process terminates using exit(3) (or equivalently, if the main thread returns).




//分离属性决定了线程退出时系统的行为,他不能决定线程的结束行为

Either  pthread_join(3) or pthread_detach() should be called for each thread that an application creates, so that system resources for the thread can be released.  (But note that the resources of all threads are freed when the process terminates.)


//如果一个线程被创建了,需要调用


pthread_join()


或者


pthread_detach(),这样线程占有的系统资源都可以被回收


EXAMPLE

The following statement detaches the calling thread:

pthread_detach(pthread_self());


//线程分离自己

CONFORMING TO

POSIX.1-2001.


三、实例

1、程序框架




2、源代码

点击(

此处

)折叠或打开



  1. /


    *


    DATE


    :

    2015



    3



    25


  2. *

    AUTHOR

    :

    WJ

  3. *


  4. *

    pthread_join

    (

    pthread_t tid

    ,

    void

    *


    *

    rval

    )


    ;


  5. *

    调用该函数ud线程会阻塞,直到线程tid终止,而且会使tid分离

  6. *

    如果tid已经分离,那么调用pthread_join就会失败

  7. *

    pthreaddetach(pthreadt, tid)

  8. *

    分离有tid制定到线程

  9. *


  10. *


    /

  11. #include

    “apue.h”

  12. void

    *

    thread_fun1

    (

    void

    *

    arg

    )


  13. {


  14. printf

    (


    “wo shi thread 1\n”


    )


    ;

  15. return

    (

    void

    *


    )

    1

    ;


  16. }

  17. void

    *

    thread_fun2

    (

    void

    *

    arg

    )


  18. {


  19. printf

    (


    “wo shi thread 2\n”


    )


    ;

  20. pthread_detach

    (

    pthread_self

    (


    )


    )


    ;

  21. pthread_exit

    (


    (

    void

    *


    )

    2

    )


    ;


  22. }


  23. int

    main

    (


    )


  24. {



  25. int

    err1

    ,

    err2

    ;

  26. pthread_t tid1

    ,

    tid2

    ;

  27. void

    *

    rval1

    ,


    *

    rval2

    ;

  28. err1

    =

    pthread_create

    (


    &

    tid1

    ,


    NULL


    ,

    thread_fun1

    ,


    NULL


    )


    ;

  29. err2

    =

    pthread_create

    (


    &

    tid2

    ,


    NULL


    ,

    thread_fun2

    ,


    NULL


    )


    ;


  30. if


    (

    err1

    |


    |

    err2

    )


  31. {


  32. printf

    (


    “create new thread failed\n”


    )


    ;

  33. return 0

    ;


  34. }

  35. printf

    (


    “wo shi main thread\n”


    )


    ;

  36. printf

    (


    “join1 rval is %d\n”


    ,

    pthread_join

    (

    tid1

    ,


    &

    rval1

    )


    )


    ;

  37. printf

    (


    “join2 rval is %d\n”


    ,

    pthread_join

    (

    tid2

    ,


    &

    rval2

    )


    )


    ;

  38. printf

    (


    “thread 1 exit code is %d\n”


    ,


    (


    int


    *


    )

    rval1

    )


    ;

  39. printf

    (


    “thread 2 exit code is %d\n”


    ,


    (


    int


    *


    )

    rval2

    )


    ;

  40. printf

    (


    “wo shi main thread\n”


    )


    ;

  41. return 0

    ;


  42. }



四、练习




点击(

此处

)折叠或打开








/


*

DATE:        2015



3



25



*

AUTHOR:        WJ


*

DESCRIPTION: 一个线程被连接成功后,另一个线程就不能再连接该线程了


*


int

pthread_join

(

pthead_t tid

,

void

*


*

rval

)


调用该函数的线程会一直阻塞,直到指定的线程tid调用pthread_exit、从启动例程返回或者被取消


*


/


#include

“apue.h”


int


err


;


pthread_t tid1

,

tid2

;

void

*

thread_fun1

(

void

*

arg

)



{




/


/

睡眠1s,让线程2先执行

sleep

(

1

)


;


printf

(


“I’m new thread1\n”


)


;

pthread_exit

(


(

void

*


)

0

)


;



}

void

*

thread_fun2

(

void

*

arg

)



{



printf

(


“I’m new thread2\n”


)


;



/


/

连接线程1


err


=

pthread_join

(

tid2

,


NULL


)


;



if


(


err


!


=

0

)



{



printf

(


“new thread2 join thread1 failed\n”


)


;



}



else



{



printf

(


“new thread2 join thread 1 success\n”


)


;



}


pthread_exit

(


(

void

*


)

0

)


;



}



int

main

(


)



{




/


/

创造新线程1


err


=

pthread_create

(


&

tid1

,


NULL


,

thread_fun1

,


NULL


)


;



if


(


err


!


=

0

)



{



printf

(


“create new thread1 failed\n”


)


;


return 0

;



}



/


/

创造新线程2


err


=

pthread_create

(


&

tid2

,


NULL


,

thread_fun2

,


NULL


)


;



if


(


err


!


=

0

)



{



printf

(


“create new thread1 failed\n”


)


;


return 0

;



}



/


/

连接线程1


err


=

pthread_join

(

tid1

,


NULL


)


;



if


(


err


!


=

0

)



{



printf

(


“main thread join thread 1 failed\n”


)


;



}



else



{



printf

(


“main thread join thread 1 success\n”


)


;



}


return 0

;



}