多线程

进程与线程

进程:

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

线程:

线程包含了表示进程内执行环境必须的信息,包括标识线程的线程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_cancel
void * 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;
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值