快捷搜索:

澳门新葡亰平台9411:进程的所有信息对该进程的

来源:http://www.fab119.com 作者:关于我们 人气:118 发布时间:2020-01-05
摘要:这里要讲的线程相关操作都是用户空间线程的操作。在Linux中,一般Pthread线程库是一套通用的线程库,是由POSIX提出的,因此具有很好的可移植性。 为什么要用线程:(其实现在我用不到

这里要讲的线程相关操作都是用户空间线程的操作。在Linux中,一般Pthread线程库是一套通用的线程库,是由POSIX提出的,因此具有很好的可移植性。
为什么要用线程:(其实现在我用不到,哈哈)
进程是系统中程序执行和资源分配的基本单位。每个进程都拥有自己的数据段、代码段和堆栈段,这就造成了进程在进行切换等操作时都需要有比较负责的上下文切换等动作。为了进一步减少处理机的空转时间支持多处理器和减少上下文切换开销,进程
在演化中出现了另一个概念——线程。它是一个进程内的基本调度单位,也可以称为轻量级进程。线程是在共享内存空间中并发的多道执行路径,它们共享一个进程的资源,如文件描述和信号处理。因此,大大减少了上下文切换的开销。

//从别处拷贝过来的,只作为自己查看方便,原作者不详,请谅解。 

Linux多线程

线程(1)

1.线程创建
函数说明
创建线程实际上就是确定调用该线程函数的入口点,这里通常使用的函数是pthread_create。在线程创建以后,就开始运行相关的线程函数,在该函数运行完之后,该线程也就退出了,这也是线程退出一种方法。另一种退出线程的方法是使用函数pthread_exit,这是线程的主动行为。这里要注意的是,在使用线程函数时,不能随意使用exit退出函数进行出错处理,由于exit的作用是使调用进程终止,往往一个进程包含多个线程,因此,在使用exit之后,该进程中的所有线程都终止了。因此,在线程中就可以使用pthread_exit来代替进程中的exit。
由于一个进程中的多个线程是共享数据段的,因此通常在线程退出之后,退出线程所占用的资源并不会随着线程的终止而得到释放。正如进程之间可以用 wait()系统调用来同步终止并释放资源一样,线程之间也有类似机制,那就是pthread_join()函数。pthread_join可以用于将当前线程挂起,等待线程的结束。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源就被收回。
#include<pthread.h>
int pthread_create ((pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)) ;
其中thread:线程标识符
attr:线程属性设置
void *(*start_routine)(void *):是一个函数指针(见程序)
成功返回0 失败返回-1
2。线程退出
#include<pthread.h>
void pthread_exit(void *retval);
函数传入值retval:pthread_exit()调用者线程的返回值,可由其他函数如 pthread_join 来检索获取
3.调入线程
#include<pthread.h>
int pthread_join((pthread_t th,void **thread_return);
其中 th:等待线程的标识符
     thread_return :用户定义的指针,用来存储被等待线程的返回值(不为NULL时)
    
/*一个简单的小线程测试程序*/
    
#include<stdio.h>
#include<pthread.h>

一:关于join 
join 
join是三种同步线程的方式之一。另外两种分别是互斥锁(mutex)和条件变量(condition variable)。 
调用pthread_join()将阻塞自己,一直到要等待加入的线程运行结束。 
可以用pthread_join()获取线程的返回值。 
一个线程对应一个pthread_join()调用,对同一个线程进行多次pthread_join()调用是逻辑错误。 
join or detach 
线程分两种:一种可以join,另一种不可以。该属性在创建线程的时候指定。 
joinable线程可在创建后,用pthread_detach()显式地分离。但分离后不可以再合并。该操作不可逆。 
为了确保移植性,在创建线程时,最好显式指定其join或detach属性。似乎不是所有POSIX实现都是用joinable作默认。 

 

本文将介绍如何使用多个控制线程在单个进程环境中执行多个任务。

void thread1(void)    /*第三步:编写pthread_join()要调用的函数*/
{
    int i=0;
    for(i=0;i<6;i++)
    {
        printf("This is a pthread1.n");
        if(i==2)
            phread_exit(0);
        sleep(1);
    }
}

二: pthread_detach 

1.线程概述

一个进程中的所有线程都可以访问该进程的组成部件(如文件描述符和内存)。

void thread2(void)
{
    int i=0;
    for(i=0;i<3;i++)
    {
        printf("This is a pthread1.n");
            phread_exit(0);
    }
}

创建一个线程默认的状态是joinable, 如果一个线程结束运行但没有被join,则它的状态类似于进程中的Zombie Process,即还有一部分资源没有被回收(退出状态码),所以创建线程者应该调用pthread_join来等待线程运行结束,并可得到线程的退出代码,回收其资源(类似于wait,waitpid) 
但是调用pthread_join(pthread_id)后,如果该线程没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此,比如在Web服务器中当主线程为每个新来的链接创建一个子线程进行处理的时候,主线程并不希望因为调用pthread_join而阻塞(因为还要继续处理之后到来的链接),这时可以在子线程中加入代码 
pthread_detach(pthread_self()) 
或者父线程调用 
pthread_detach(thread_id)(非阻塞,可立即返回) 
这将该子线程的状态设置为detached,则该线程运行结束后会自动释放所有资源。 

线程是一个进程内的基本调度单位,也可以称为轻量级进程。线程是在共享内存空间中并发的多道执行路径,它们共享一个进程的资源,如文件描述和信号处理。因此,大大减少了上下文切换的开销。一个进程可以有多个线程,也就

线程包含了表示进程内执行环境必须的信息,其中包括进程中标识线程的线程ID、一组寄存器值、栈、调度优先级和策略、信号屏蔽字、errno变量以及线程私有数据。进程的所有信息对该进程的所有线程都是共享的,包括可执行的程序文本、程序的全局内存和堆内存、栈以及文件描述符。

int main(void)
{
    pthread_t id1,id2;
    int i,ret;
    ret=pthread_create(&id1,NULL,(void *)thread1,NULL);/*第一步调用pthread_create();*/
    if(ret!=0)
    {
        printf("Create pthread error!n");
        exit(1);
    }
    ret=pthread_create(&id2,NULL,(void *)thread2,NULL);
    if(ret!=0)
    {
        printf("Create pthread error!n");
        exit(1);
    }
    pthread_join(id1,NULL);                    /*第二步调用pthread_join();*/
    pthread_join(id2,NULL);
    
    return 0;
}

三:pthread_join 
调用pthread_join的线程会阻塞,直到指定的线程返回,调用了pthread_exit,或者被取消。 
    如果线程简单的返回,那么rval_ptr被设置成线程的返回值,参见范例1;如果调用了pthread_exit,则可将一个无类型指针返回,在pthread_join中对其进行访问,参见范例2;如果线程被取消,rval_ptr被设置成PTHREAD_CANCELED。 
    如果我们不关心线程的返回值,那么我们可以把rval_ptr设置为NULL。 

是有多个线程控制表及堆栈寄存器,但却共享一个用户地址空间。

线程标识

范例1: 
#include <pthread.h> 
#include <string.h> 

 

进程ID在整个系统中是唯一的。每个线程ID,线程ID只在它所属的进程环境中有效。

void *thr_fn1(void *arg) 

    printf(“thread 1 returning.n”); 
    return((void *)1); 

2.线程实现

在线程中,线程ID的类型是pthread_t类型,由于在Linux下线程采用POSIX标准,所以,在不同的系统下,pthread_t的类型是不同的,比如在ubuntn下,是unsigned long类型,而在solaris系统中,是unsigned int类型。而在FreeBSD上才用的是结构题指针。 所以不能直接使用==判读,而应该使用pthread_equal来判断。

void *thr_fn2(void *arg) 

    printf(“thread 2 exiting.n”); 
    return((void *)2); 

 

#include<pthread.h>

int main() 

    pthread_t tid1,tid2; 
    void *tret; 
    pthread_create(&tid1,NULL,thr_fn1,NULL); 
    pthread_create(&tid2,NULL,thr_fn2,NULL); 
    pthread_join(tid1,&tret); 
    printf(“thread 1 exit code %dn”,(int)tret); 
    pthread_join(tid2,&tret); 
    printf(“thread 2 exit code %dn”,(int)tret); 
    exit(0); 

线程创建pthread_create()

intpthread_equal(pthread_t t1, pthread_t t2);

运行结果: 
thread 1 returning. 
thread 1 exit code 1. 
thread 2 exiting. 
thread 2 exit code 2. 

  所需头文件#include <pthread.h>

返回值:若相等则返回非0值,否则返回0。

范例2: 
#include <stdio.h> 
#include <pthread.h> 

函数原型int pthread_create ((pthread_t *thread, pthread_attr_t *attr,

线程可以通过调用

void thread1(char s[]) 

        printf("This is a pthread1.n"); 
        printf("%sn",s); 
        pthread_exit("Hello first!");  //结束线程,返回一个值。 

void *(*start_routine)(void *), void *arg))

#include<pthread.h>

void thread2(char s[]) 

        printf("This is a pthread2.n"); 
        printf("%sn",s); 
        pthread_exit("Hello second!"); 

thread:线程标识符

pthread_tpthread_self(void);

int main(void) 

        pthread_t id1,id2; 
        void *a1,*a2; 
        int i,ret1,ret2; 
        char s1[]="This is first thread!"; 
        char s2[]="This is second thread!"; 
        ret1=pthread_create(&id1,NULL,(void *) thread1,s1); 

attr:线程属性设置

返回值是调用线程的线程。

        ret2=pthread_create(&id2,NULL,(void *) thread2,s2); 

start_routine:线程函数的起始地址

线程创建
创建线程可以调用pthread_create函数创建。

        if(ret1!=0){ 
                printf ("Create pthread1 error!n"); 
                exit (1); 
        } 
        pthread_join(id1,&a1); 

arg:传递给start_routine的参数

#include<pthread.h>

        printf("%sn",(char*)a1); 

函数返回值 成功:0 出错:-1

intpthread_create(pthread_t *thread, const pthread_attr_t *attr,

        if(ret2!=0){ 
                printf ("Create pthread2 error!n"); 
                exit (1); 
        } 
        printf("This is the  main process.n"); 
        pthread_join(id2,&a2); 
        printf("%sn",(char*)a2); 
        return (0); 

 

                          void*(*start_routine) (void *), void *arg);

运行结果: 
[****@XD**** c]$ ./example 
This is a pthread1. 
This is first thread! 
Hello first! 
This is the main process. 
This is a pthread2. 

线程退出pthread_exit();

返回值:若成功则返回0,否则返回错误编号

<参考资料语> 

 所需头文件#include <pthread.h>

当pthread_create成功返回时,由thread指向的内存单元被设置为新创建线程的线程ID。attr参数用于定制各种不同的线程属性。将attr设置为NULL,创建默认属性的线程。

一般情况下,进程中各个线程的运行都是相互独立的,线程的终止并不会通知,也不会影响其他线程,终止的线程所占用的资源也并不会随着线程的终止而得到释 放。正如进程之间可以用wait()系统调用来同步终止并释放资源一样,线程之间也有类似机制,那就是pthread_join()函数 

函数原型void pthread_exit(void *retval)

新创建的线程从start_routine函数地址开始运行,该函数只有一个无类型指针参数arg,如果需要向start_routine函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。

pthread_join()的调用者将挂起并等待th线程终止,retval是pthread_exit()调用者线程(线程ID为th)的返回值,如 果thread_return不为NULL,则*thread_return=retval。需要注意的是一个线程仅允许唯一的一个线程使用 pthread_join()等待它的终止,并且被等待的线程应该处于可join状态,即非DETACHED状态 

函数传入值retval:pthread_exit()调用者线程的返回值,可由其他函数如pthread_join 来检索获取

线程创建时并不能保证哪个线程会先运行:是新创建的线程还是调用线程。新创建的线程可以访问进程的地址空间,并且继承调用线程的浮点环境和信号屏蔽字,但该线程的未决信号集被清除。

如果进程中的某个线程执行了pthread_detach(th),则th线程将处于DETACHED状态,这使得th线程在结束运行时自行释放所占用的 内存资源,同时也无法由pthread_join()同步,pthread_detach()执行之后,对th请求pthread_join()将返回错误 

 

下面的程序创建了一个线程并且打印进程ID、新线程的线程ID以及初始化线程的线程ID。

一个可join的线程所占用的内存仅当有线程对其执行了pthread_join()后才会释放,因此为了避免内存泄漏,所有线程的终止,要么已设为DETACHED,要么就需要使用pthread_join()来回收 

等待线程退出并释放资源pthread_join()

[cpp] view plaincopyprint?01.#include <stdio.h>  
02.#include <stdlib.h>  
03.#include <pthread.h>  
04. 
05.pthread_t ntid; 
06. 
07.void printids(const char *s) 
08.{ 
09.    pid_t       pid; 
10.    pthread_t   tid; 
11. 
12.    pid = getpid(); 
13.    tid = pthread_self(); 
14.    printf("%s pid %u tid %u (0x%x)n", s, (unsigned int)pid, 
15.      (unsigned int)tid, (unsigned int)tid); 
16.} 
17. 
18.void * thr_fn(void *arg) 
19.{ 
20.    printids("new thread: "); 
21.return((void *)0); 
22.} 
23. 
24.void err_quit(const char* fmt, ...) 
25.{ 
26.printf("%sn",fmt); 
27.exit(1); 
28.} 
29. 
30. 
31.int main(void) 
32.{ 
33.    int     err; 
34. 
35.    err = pthread_create(&ntid, NULL, thr_fn, NULL); 
36.    if (err != 0) 
37.        err_quit("can't create thread: %sn", strerror(err)); 
38.printids("main thread:"); 
39.    sleep(1); 
40.    exit(0); 
41.} 
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

3) 主线程用pthread_exit还是return 

  所需头文件#include <pthread.h>

pthread_t ntid;

用pthread_exit只会使主线程自身退出,产生的子线程继续执行;用return则所有线程退出。 

函数原型int pthread_join ((pthread_t th, void **thread_return))

void printids(const char *s)
{
    pid_t       pid;
    pthread_t   tid;

综合以上要想让子线程总能完整执行(不会中途退出),一种方法是在主线程中调用pthread_join对其等待,即pthread_create/pthread_join/pthread_exit或return;一种方法是在主线程退出时使用pthread_exit,这样子线程能继续执行,即pthread_create/pthread_detach/pthread_exit;还有一种是pthread_create/pthread_detach/return,这时就要保证主线程不能退出,至少是子线程完成前不能退出。现在的项目中用的就是第三种方法,主线程是一个死循环,子线程有的是死循环有的不是。 

函数传入值

    pid = getpid();
    tid = pthread_self();
    printf("%s pid %u tid %u (0x%x)n", s, (unsigned int)pid,
      (unsigned int)tid, (unsigned int)tid);
}

<参考资料语> 

th:等待线程的标识符

void * thr_fn(void *arg)
{
    printids("new thread: ");
return((void *)0);
}

理论上说,pthread_exit()和线程宿体函数退出的功能是相同的,函数结束时会在内部自动调用pthread_exit()来清理线程相关的资源。但实际上二者由于编译器的处理有很大的不同。 

thread_return:用户定义的指针,用来存储被等待线程的返回值(不为NULL时)

void err_quit(const char* fmt, ...)
{
printf("%sn",fmt);
exit(1);
}

在进程主函数(main())中调用pthread_exit(),只会使主函数所在的线程(可以说是进程的主线程)退出;而如果是return,编译器将使其调用进程退出的代码(如_exit()),从而导致进程及其所有线程结束运行。 

函数返回值  成功:0  出错:-1

int main(void)
{
    int     err;

 

    err = pthread_create(&ntid, NULL, thr_fn, NULL);
    if (err != 0)
        err_quit("can't create thread: %sn", strerror(err));
printids("main thread:");
    sleep(1);
    exit(0);
}

代码举例

编译:

1.    #include<pthread.h>

 pthread 库不是 Linux 系统默认的库,连接时需要使用静态库 libpthread.a,所以在使用pthread_create()创建线程,以及调用 pthread_atfork()函数建立fork处理程序时,需要链接该库。

2.    #include<stdio.h>

gcc creatThread.c –lpthread

3.    #include<errno.h>

执行及输出:

4.   

./a.out

5.    /*线程1*/

main thread: pid2846 tid 3079362240 (0xb78b56c0)

6.    void thread1()

new thread:  pid 2846 tid 3079359344 (0xb78b4b70)

7.    {

主线程需要休眠,否则整个进程有可能在新线程进入运行之前就终止了。新线程是通过pthread_self()来获取自己的线程ID,而不是从共享内存中读出或者从线程的启动例程中以参数接收到。pthread_create函数会通过第一个参数返回新建线程的ID。在本例中,新建线程ID被放在ntid中,但是如果新线程在主线程调用pthread_create返回之前就运行了,那么新线程看到的是未初始化的ntid内容。

8.        int i=0;

线程终止

9.        

如果进程中的任一线程调用了exit,_Exit或者_exit,那么整个进程就会终止。一次类似,如果信号的默认动作是终止进程,那么,把该信号发送到线程会终止整个进程。

10.           while(1)

但线程可以通过下列三种方式退出:

11.           {

1.      线程只是从启动例程中返回,返回值是线程的退出码

12.        printf("thread1:%dn",i);

2.      线程可以被同一进程中的其他线程取消

13.        if(i>3)

3.      线程调用pthread_exit

14.           pthread_exit(0);

pthread_exit函数:

15.        i++;

 #include<pthread.h>

16.        sleep(1);

voidpthread_exit(void *retval);

17.       }

retval 是一个无类型的指针,与传给启动例程的单个参数类似。进程中的其他线程可以通过调用pthread_join函数访问到这个指针。

18.   }

#include<pthread.h>

19.  

intpthread_join(pthread_t thread, void **retval);

20.   /*线程2*/

返回值:若成功则返回0,否则返回错误编号

21.   void thread2()

调用pthread_join函数的线程将一直被阻塞,直到指定的线程调用pthread_exit 、从启动例程中返回或者被取消。如果线程只是从它的启动例程返回,retval 将包含返回码。如果线程被取消,retval 指定的内存单元就设置为PTHREAD_CANCELED。

22.   {

[cpp] view plaincopyprint?01.#include<stdio.h>  
02.#include<stdlib.h>  
03.#include<pthread.h>  
04.  
05.void * thr_fn1(void*arg) 
06.{ 
07.    printf("thread 1 returningn"); 
08.    return((void *)1); 
09.} 
10.  
11.void * thr_fn2(void*arg) 
12.{ 
13.    printf("thread 2 exitingn"); 
14.    pthread_exit((void *)2); 
15.} 
16.voiderr_quit(const char* fmt, ...) 
17.{ 
18.    printf("%sn",fmt); 
19.    exit(1); 
20.} 
21.int main(void) 
22.{ 
23.    int        err; 
24.    pthread_t  tid1, tid2; 
25.    void       *tret; 
26.  
27.    err = pthread_create(&tid1, NULL,thr_fn1, NULL); 
28.    if (err != 0) 
29.    { 
30.        err_quit("can't create thread 1:%sn", strerror(err)); 
31.  
32.    } 
33.    err = pthread_create(&tid2, NULL,thr_fn2, NULL); 
34.    if (err != 0) 
35.        err_quit("can't create thread 2:%sn", strerror(err)); 
36.err = pthread_join(tid1, &tret); 
37.if (err != 0) 
38.        err_quit("can'tjoin with thread 1: %sn", strerror(err)); 
39.    printf("thread 1 exitcode %dn", (int)tret); 
40.    err = pthread_join(tid2,&tret); 
41.    if (err != 0) 
42.        err_quit("can'tjoin with thread 2: %sn", strerror(err)); 
43.    printf("thread 2 exitcode %dn", (int)tret); 
44.    exit(0); 
45.} 
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
 
void * thr_fn1(void*arg)
{
    printf("thread 1 returningn");
    return((void *)1);
}
 
void * thr_fn2(void*arg)
{
    printf("thread 2 exitingn");
    pthread_exit((void *)2);
}
voiderr_quit(const char* fmt, ...)
{
    printf("%sn",fmt);
    exit(1);
}
int main(void)
{
    int        err;
    pthread_t  tid1, tid2;
    void       *tret;
 
    err = pthread_create(&tid1, NULL,thr_fn1, NULL);
    if (err != 0)
    {
        err_quit("can't create thread 1:%sn", strerror(err));
 
    }
    err = pthread_create(&tid2, NULL,thr_fn2, NULL);
    if (err != 0)
        err_quit("can't create thread 2:%sn", strerror(err));
err = pthread_join(tid1, &tret);
if (err != 0)
        err_quit("can'tjoin with thread 1: %sn", strerror(err));
    printf("thread 1 exitcode %dn", (int)tret);
    err = pthread_join(tid2,&tret);
    if (err != 0)
        err_quit("can'tjoin with thread 2: %sn", strerror(err));
    printf("thread 2 exitcode %dn", (int)tret);
    exit(0);
}

23.       int i=0;

运行及输出:

24.       

thread 2 exiting

25.           while(1)

thread 1 returning

26.           {

thread 1 exit code 1

27.        printf("thread2:%dn",i);

thread 2 exit code 2

28.        if(i>5)

可以看出当一个线程通过调用pthread_exit退出或简单地从启动例程中返回时,进程中的其他线程可以通过调用pthread_join函数获得该线程的退出状态。

29.           pthread_exit(0);

pthread_exit和pthread_create函数的无类型指针参数可能传递一个复杂的结构的地址,单数该结构所使用的内存调用者完成调用以后必须仍然是有效的。可以使用全局结构或者malloc函数分配栈结构。

30.        i++;

线程可以通过调用pthread_cancel函数请求取消同一进程中的其他线程。

31.        sleep(1);

#include <pthread.h>

32.       }

int pthread_cancel(pthread_t thread);

33.   }

返回值:若成功则返回0,否则返回错误编号。

34.  

在默认情况下,pthread_cancel函数会使得由thread标识的线程的行为表现为如同调用了参数为PTHREAD_CANCELED的pthread_exit函数,但是线程可以选择忽略取消方式或是控制取消方式。

35.   int main()

线程可以安排它退出时需要调用的函数,这与进程可以用atexit函数安排进程退出时需要调用的函数时类似的。这样的函数成为线程清理处理程序。线程可以建立多个清理程序。处理程序记录在栈中,也就是说它们的执行顺序与它们注册时的顺序相反。

36.   {

 #include<pthread.h>

37.   pthread_t t1,t2;

voidpthread_cleanup_push(void (*routine)(void *), void *arg);

38.  

voidpthread_cleanup_pop(int execute);

39.   /*创建线程*/

当线程执行以下动作时调用清理函数,调用参数为arg,清理函数routine的调用顺序是由pthread_cleanup_push函数安排的。

40.   pthread_create(&t1,NULL,(void *)thread1,NULL);

1.调用pthread_exit时

41.   pthread_create(&t2,NULL,(void *)thread2,NULL);

2.响应取消请求时

42.   /*等待线程退出*/

3.用非零execute参数调用voidpthread_cleanup_pop时

43.   pthread_join(t1,NULL);

如果execute为0,清理函数将不被调用。无论哪种情况,pthread_cleanup_pop都将删除上次pthread_cleanup_push调用建立的清理处理程序。

44.   pthread_join(t2,NULL);

如下程序显示了如何使用线程清理处理程序。

45.   return 0;

[cpp] view plaincopyprint?01.#include <stdio.h>  
02.#include <stdlib.h>  
03.#include <pthread.h>  
澳门新葡亰平台9411,04.  
05.void cleanup(void *arg) 
06.{ 
07.   printf("cleanup: %sn", (char *)arg); 
08.} 
09.  
10.void * thr_fn1(void *arg) 
11.{ 
12.   printf("thread 1 startn"); 
13.   pthread_cleanup_push(cleanup, "thread 1 first handler"); 
14.   pthread_cleanup_push(cleanup, "thread 1 second handler"); 
15.   printf("thread 1 push completen"); 
16.   if (arg) 
17.       return((void *)1); 
18.   pthread_cleanup_pop(0); 
19.   pthread_cleanup_pop(0); 
20.return((void*)1); 
21.} 
22.  
23.void * thr_fn2(void *arg) 
24.{ 
25.printf("thread2 startn"); 
26.pthread_cleanup_push(cleanup,"thread 2 first handler"); 
27.pthread_cleanup_push(cleanup,"thread 2 second handler"); 
28.printf("thread2 push completen"); 
29.if (arg) 
30.    pthread_exit((void *)2); 
31.pthread_cleanup_pop(0); 
32.pthread_cleanup_pop(0); 
33.pthread_exit((void*)2); 
34.} 
35.  
36.void err_quit(const char* fmt, ...) 
37.{ 
38.printf("%sn",fmt); 
39.exit(1); 
40.} 
41.  
42.int main(void) 
43.{ 
44.int         err; 
45.pthread_t   tid1, tid2; 
46.void        *tret; 
47.  
48.err =pthread_create(&tid1, NULL, thr_fn1, (void *)1); 
49.if (err != 0) 
50.err_quit("can't create thread 1: %sn", strerror(err)); 
51.  err =pthread_create(&tid2, NULL, thr_fn2, (void *)1); 
52.if (err != 0) 
53.err_quit("can't create thread 2: %sn", strerror(err)); 
54.err =pthread_join(tid1, &tret); 
55.if (err != 0) 
56.err_quit("can't join with thread 1: %sn", strerror(err)); 
57.printf("thread1 exit code %dn", (int)tret); 
58.err =pthread_join(tid2, &tret); 
59.if (err != 0) 
60.err_quit("can't join with thread 2: %sn", strerror(err)); 
61.printf("thread2 exit code %dn", (int)tret); 
62.exit(0); 
63.} 
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
 
void cleanup(void *arg)
{
   printf("cleanup: %sn", (char *)arg);
}
 
void * thr_fn1(void *arg)
{
   printf("thread 1 startn");
   pthread_cleanup_push(cleanup, "thread 1 first handler");
   pthread_cleanup_push(cleanup, "thread 1 second handler");
   printf("thread 1 push completen");
   if (arg)
       return((void *)1);
   pthread_cleanup_pop(0);
   pthread_cleanup_pop(0);
return((void*)1);
}
 
void * thr_fn2(void *arg)
{
printf("thread2 startn");
pthread_cleanup_push(cleanup,"thread 2 first handler");
pthread_cleanup_push(cleanup,"thread 2 second handler");
printf("thread2 push completen");
if (arg)
    pthread_exit((void *)2);
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
pthread_exit((void*)2);
}
 
void err_quit(const char* fmt, ...)
{
printf("%sn",fmt);
exit(1);
}
 
int main(void)
{
int         err;
pthread_t   tid1, tid2;
void        *tret;
 
err =pthread_create(&tid1, NULL, thr_fn1, (void *)1);
if (err != 0)
err_quit("can't create thread 1: %sn", strerror(err));
  err =pthread_create(&tid2, NULL, thr_fn2, (void *)1);
if (err != 0)
err_quit("can't create thread 2: %sn", strerror(err));
err =pthread_join(tid1, &tret);
if (err != 0)
err_quit("can't join with thread 1: %sn", strerror(err));
printf("thread1 exit code %dn", (int)tret);
err =pthread_join(tid2, &tret);
if (err != 0)
err_quit("can't join with thread 2: %sn", strerror(err));
printf("thread2 exit code %dn", (int)tret);
exit(0);
}

46.   }

执行及输出结果如下:

3同步与互斥

thread 2 start

<1>互斥锁

thread 2 push complete

 互斥锁的操作主要包括以下几个步骤。

cleanup: thread 2 second handler

本文由澳门新葡亰平台9411发布于关于我们,转载请注明出处:澳门新葡亰平台9411:进程的所有信息对该进程的

关键词:

最火资讯