多线程

来源:互联网 发布:macbook air破解软件 编辑:程序博客网 时间:2024/06/05 05:16

进程与线程

进程:

首先进程是一个实体,每一个进程都有自己的内存地段,进程是执行中的程序,但程序是一个没有生命的实体。进程是操作系统中最基本的,最重要的概念。

线程:

线程包含了表示进程内执行环境必须的信息,包括标识线程的线程ID,一组寄存器值,栈,调度优先级和策略,信号屏蔽字,errno变量以及线程私有数据。

每一个程序至少有一个线程。一个进程在同一时间只能做一件事,多线程可以同时做多件事,每个线程可以处理不同的事物,一个线程阻塞,另一个线程并不会受到影响。

进程中的所有信息在线程中都是共享的,线程中有自己的栈。包括执行代码,全局变量,和堆内存,栈以及文件描述符。

线程标识
  –就像每个进程有个进程ID一样,线程也有自己的ID。
  –进程ID用pid_t来表示,它是一个unsigned int。
  –线程ID用pthread_t表示,pthread_t不能把它当整数处理。
  –线程可以通过pthread_self()函数获得自身的线程ID

线程创建:

在进程中只有一个控制线程即主线程,程序是以单线程启动的,在创建了多个线程以后,若用gcc编译的时候,需要在最后添加-lpthread选项,目地是(链接叫libpthread.oo这个库)

#include<pthread.h>

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

参数thread 是一个指针,当线程成功创建,返回创建线程的ID

参数addr 用于指定线程的属性,一般设为NULL(即表示此线程为不可分离状态);

参数start_routine 是一个函数指针,指向线程创建后要调用的函数(回调函数)

参数arg 传递给线程函数的参数

成功返回0

pthread_create实例1:

void *func(void *arg){    printf("pthread start\n");    return NULL;}int main(int arg, char * args[]){    pthread_t thr_d;    int err = pthread_create(&thr_d, NULL, func, NULL);    if (err != 0)    {        printf("create pthread failed\n");    }    else    {        printf("create pthread success\n");    }    sleep(1);    return 0;}

实例2:

void * func1(void * arg){printf("pthread1 start\n");sleep(1);printf("pthread1 end\n")return 0;}void * func2(void * arg){printf("pthread2 start\n");while(1){printf("hehe\n");sleep(1);}printf("pthread2 end\n")return 0;}int main(void){pthread_t thid1,thid2;if(pthread_create(&thid1,NULL,func1,NULL) != 0){printf("error is %s\n",strerror(errno));}if(pthread_create(&thid2,NULL,func2,NULL) != 0){printf("error is %s\n",strerror(errno));}while(1){sleep(1);}return EXIT_SUCCESS;}


线程终止:

1 任何线程调用exit函数,整个进程会被杀死

2 调用pthread_exit()函数,使线程退出,进程并不会死

3 线程中使用return ;是线程退出

4 线程可以被同一进程中的其他线程取消,pthread_cancel


void pthread_exit(void *arg);

arg是一个无类型的指针,该指针会被其他线程调用

实例:

void *func(void *arg){    printf("pthread start\n");    pthread_exit(0);}int main(int arg, char * args[]){    pthread_t thr_d;    pthread_create(&thr_d, NULL, func, NULL);    sleep(1);    return 0;}

线程挂起:此函数用于挂起当前线程,直到th指定的线程终止为止

int pthread_join(pthread_t th,void ** thr_return);

参数:th 即线程ID,指定被挂起的线程ID号

参数:thr_return ,是指向线程th返回的指针,也可为null

pthread_join()实例:

void * func1(void * arg){sleep(5);return NULL;}int main(){pthread_t thid;int i1 = 1,i2 = 2;if(pthread_create(&thid,NULL,func1,&i1) != 0){printf("error is %s\n",strerror(errno));}int *p = NULL;//pthread_join的第二个参数是指向线程thid返回的指针pthread_join(thid,(void **) &p);//pthread_join(thid,null);printf("p = %d\n",*p);printf("main end\n");return 0;}

int pthread_cancel(pthread_t th);
pthread_cancel函数允许一个线程取消th指定的另一个线程。
函数成功,返回0,否则返回非0。
pthread_cancel实例:

void *func1(void *arg){    printf("pthread%d start\n",i1);    while(1)    {        printf("thread%d is running\n",i1);        sleep(1);    }    pthread_exit(NULL);}void *func2(void *arg){    printf("pthread%d start\n",i2);    sleep(5);    pthread_cancel(thr_d1);    printf("pthread%d end\n",i2);    pthread_exit(NULL);}int main(int arg, char * args[]){pthread_t thr_d1,thr_d2;int i1 = 1,i2 = 2;pthread_create(&thr_d1, NULL, func1, &i1);    pthread_create(&thr_d2, NULL, func2, &i2);    sleep(6);    printf("end\n");    return 0;}



int pthread_detach(pthread_t th);

pthread_detach函数使线程处于被分离状态。
对于被分离状态的线程,不需要调用pthread_join,如果其他线程调用pthread_join失败,返回EINVAL。
如果不等待一个线程,同时对线程的返回值不感兴趣,可以设置这个线程为被分离状态,让系统在线程退出的时候自动回收它所占用的资源。
一个线程不能自己调用pthread_detach改变自己为被分离状态,只能由其他线程调用pthread_detach。
线程默认状态为不可分离状态,即pthread_create的第二个参数为null

实例:

void * func1(void * arg){printf("child pthread start\n");while(1){sleep(1);printf("child pthread end\n");}pthread_exit(0);}//线程退出有三种方法,其中之一可以是在一个线程中结束另一个线程pthread_cancelvoid * func2(void * arg){//因为线程ID为pthread_t类型,并不是一个整型sleep(5);pthread_t thr;thr = *(pthread_t *) arg;pthread_cancel(thr);pthread_exit(0);}int main(){pthread_t thid1,thid2;int i1 = 1,i2 = 2;if(pthread_create(&thid1,NULL,func1,NULL) != 0){printf("pthread error\n");}if(pthread_create(&thid2,NULL,func2,&thid1) != 0){printf("pthread error\n");}pthread_detach(thid1);pthread_join(thid2,NULL);printf("main end\n");return 0;}

线程属性:

          以前调用pthread_create传入的attr参数都是空指针,而不是指向pthread_attr_t结构的指针。

  –可以使用pthread_attr_t结构修改线程默认属性,并把这些属性与创建的线程联系起来
  –可以使用pthread_attr_init函数初始化pthread_attr_t结构。
  –调用pthread_attr_init以后,pthread_arrt_t的结构所包含的内容就是操作系统实现支持线程所有属性的默认值。如果要修改其中个别属性的值,需要调用其他函数。

int pthread_attr_init(pthread_addr_t * attr); // 线程结构初始化函数

int pthread_attr_destroy(phttp://www.cnblogs.com/shichuan/p/4496160.htmlthread_attr_t *attr); // 释放attr内存空间的函数

int pthread_attr_setdetachstate(pthread_attr_t *attr,int detachstate);
 // 参数detachstate有两个合法值,PTHREAD_CREATE_DETACHED 设置线程为分离状态
//PTHREAD_CREATE_JOINABLE 设置线程为正常状态

可以通过pthread_attr_t 在创建线程的时候就指定线程属性为分离状态,而不用创建以后再去修改线程属性。
使用步骤:
1 使用pthread_attr_init 函数初始化pthread_attr_t结构。
2 pthread_attr_setdetachstate(pthread_attr_t *attr,int detachstate);
3 pthread_attr_destroy(pthread_attr_t *attr);//释放attr内存空间
实例:
void *func(void *arg){    printf("pthread start\n");    while(1)    {        printf("thread is running\n");        sleep(1);    }    pthread_exit(NULL);}int main(int arg, char * args[]){    pthread_t thr_d;    pthread_attr_t attr;    pthread_attr_init(&attr);    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);    pthread_create(&thr_d, &attr, func, NULL);    pthread_attr_destroy(&attr);    sleep(2);    printf("end\n");    return 0;}








0 0