线程

 堆栈

  线程包含线程ID,寄存器的值栈。

 堆属于整个进程, 栈属于线程级别的。

 一个进程可能出现多个栈,线程之间的栈是独立的,但是可以互相访问的。调度优先级,等属于线程的。

 errno属于线程的,在线程栈中

 CPU同一时间只能执行一条指令。进程内所有的信息对于线程都是共享的,包括执行代码,全局变量,和堆内存,栈以及文件描述符。

 线程标识:

    进程用pid_t表示,是一个unsigned int

    线程ID用pthread_t表示,pthread_t不能把它当整数处理。

    线程可以通过pthread_self()函数获得自身的线程ID。

 

线程创建:

-一个进程最少有一个线程,单线程方式启动。。

在进程中只有一个控制线程,捕捉信号函数最好写在控制线程中,否则程序会别的异常复杂。

程序开始运行的时候每个进程只有一个线程。它以当线程的方式启动。在创建多个线程以前,进程的行为,与传统的进程没有区别。

gcc 在链接的时候需要增加-lpthread选项。-lpthread 表示链接libpthread.so库。

创建一个线程调用pthread_create函数。

 

#include <pthread.h>

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

第一个参数:线程id

第二个参数:一般为NULL 线程的一些属性

第三个参数:线程回调函数

第四个参数:传递给线程回调函数的参数

 创建成功返回零,失败返回错误码。errno

 ps -eLF 查看线程。

线程退出

1. 在启动函数中返回,返回值是线程退出码

2.线程可以在同一个进程中的线程取消。

3.调用exit();函数

4.调用pthread_exit函数。

 

线程调用:

线程与线程调用时异步并行随机的。

#include <pthread.h>

int pthread_join(pthread_t thread, void **retval);  类似wait();

第一个参数ID号,第二个是无类型的二级指针。

 挂起当前进程,直达参数thread指定的线程终止为止。

如果另一个线程返回不是NULL,则保持在retval地址中。

一个线程所使用的内存资源在应用pthread_join调用之前不会被重新分配,所以对于每个线程必须调用一次pthread_join函数。

 例子:

/////////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include<unistd.h>
#include<sys/types.h>
#include<errno.h>
#include<signal.h>
#include <pthread.h>
#include<string.h>
#include<malloc.h>

void* func12(void *num)
{
int p = *(int*)num;//得到num[]数组的值

free(num);
while(1)
{
printf("thread%d start..\n" , p );
sleep(1);
break;
}

int *a ;

 a=malloc(sizeof(int));

*a = 100;
return a;//代表线程已经结束了。
}

 

void* func3(void *num)
{

while(1)
{
printf("thread3 start..\n" );
sleep(1);
// break;
}
pthread_exit(NULL);//线程可以被同一进程中的其他线程取消掉。
return NULL;//这一句就不会执行啦。。
}

 

void creat_thread()
{
pthread_t thr1 ,thr2;
//int num[2];//这是局部变量,函数执行完成后,内存会释放掉。所以加static,或malloc
//num[0] = 1;
//num[1] = 2;
int *num1,*num2;
num1 = (int*)malloc(sizeof(int));
num2 = (int*)malloc(sizeof(int));

*num1 = 1;
*num2 = 2;
if( pthread_create(&thr1 , NULL , func12 , num1) )//返回非零表示成果,传递num[]值 同时执行func函数
{
printf("thread1 error :%s\n" , strerror(errno));

}

if( pthread_create(&thr2 , NULL , func12 , num2) )//传递num[]值 同时执行func函数
{
printf("thread2 error :%s\n" , strerror(errno));
}

int *p = NULL;
pthread_join(thr1 , (void*)&p);//主线程挂起,等待thr1线程的结束
pthread_join(thr2 , NULL);//主线程挂起,等待thr2线程的结束
printf("p= %d" , *p);

 free(p);
}

//main函数里面的栈与线程中的栈是可以相互访问的。
int main(void)
{

puts("pthread start!");
pthread_t thr3 ,thr4,thr5,thr6 ,thr7;

creat_thread();
if( pthread_create(&thr3 , NULL , func3 , NULL) )//线程函数func3
{
printf("thread2 error :%s\n" , strerror(errno));
}


return EXIT_SUCCESS;
}

/////////////////////////////////////////////////////////////////////////////////////////

 

线程分离

#include <pthread.h>

int pthread_detach(pthread_t thread);

一旦线程成为分离线程后,就不能再使用pthread_join了

可分离线程的使用:

1.主线程不需要等待子线程。

2.主线程不关心子线程的返回码

 

#include <pthread.h>

int pthread_cancel(pthread_t thread);

另一个线程中终止另外的线程。

 //////////////////////////////////////////////////////////////////////////////

 

/*
============================================================================
Name : thread.c
Author :
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include<unistd.h>
#include<sys/types.h>
#include<errno.h>
#include<signal.h>
#include <pthread.h>
#include<string.h>
#include<malloc.h>

 


void* func3(void *num)
{
while(1)
{
printf("thread3 start..\n" );

}

return NULL;//这一句就不会执行啦。。
}

void* func2(void *num)
{
pthread_t id = *(pthread_t*)num;
sleep(5);
printf("thread2 start..\n" );
pthread_cancel(id);
printf("thread2 end..\n" );

return NULL;//这一句就不会执行啦。。
}
void* func1(void *num)
{
printf("thread1 start..\n" );
while(1)
{
sleep(1);
printf("thread1 living..\n" );

}
printf("thread1 end..\n" );
return NULL;//这一句就不会执行啦。。
}


//main函数里面的栈与线程中的栈是可以相互访问的。
int main(void)
{

puts("pthread start!");
pthread_t thr1,thr2 , thr3 ;

if( pthread_create(&thr1 , NULL , func1 , NULL) )//线程函数func3
{
printf("thread1 error :%s\n" , strerror(errno));
}
if( pthread_create(&thr2 , NULL , func2 , &thr1 ) )//线程函数func3
{
printf("thread2 error :%s\n" , strerror(errno));
}
if( pthread_create(&thr3 , NULL , func3, NULL ) )//线程函数func3
{
printf("thread3 error :%s\n" , strerror(errno));
}

pthread_detach(thr3);//设置为可分离线程 使用场景:1.主线程不需要等待子线程,也不关心子线程的返回码 ,使用pthread_join(thr3 ,NULL);已经没有用了。
pthread_join(thr1,NULL);
pthread_join(thr2 , NULL);

return EXIT_SUCCESS;
}

//////////////////////////////////////////////////////////////////////////////////

#include <pthread.h>

int pthread_equal(pthread_t t1, pthread_t t2);

 比较2个线程id是否相同,相同返回非零。不同返回0.。不能像进程那样直接if(pid1 == pid2)而必须使用此函数来判断线程id是否相等

 

线程属性:

pthread_creat函数第二个参数,以前调用pthread_create传入的attr参数都是空指针,而不是指向pthread_attr_t结构的指针,

可以使用pthread_attr_t结构修改线程默认属性,并把这些属性与创建的线程联系起来。

可以使用pthread_attr_init函数初始化pthread_attr_t结构。

调用pthread_attr_init以后,pthread_arrt_t的结构所包含的内容就是操作系统实现支持线程所有属性的

默认值。如果要修改其中个别属性的值,需要调用其他函数。

 

#include <pthread.h>

int   pthread_attr_init(pthread_attr_t *attr);

      pthread_attr_init初始化pthread_attr_t结构。


int pthread_attr_destroy(pthread_attr_t *attr);

      pthread_attr_destroy函数释放attr内存空间。

 

 pthread_attr_t结构对于应用程序来讲是不透明的,应用程序不需要了解有关结构的内部组成。

 pthread_detach在创建线程的时候就指定线程属性为detach,而不是创建以后再去修改线程的属性。

 

#include <pthread.h>

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

函数pthread_attr_setdetachstate把线程属性设置为下面合法值之一

PTHREAD_CREATE_DETACHED 设置线程为分离状态

 

PTHREAD_CREATE_JOINABLE  设置线程为正常状态 默认状态


int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);

 

///////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include<unistd.h>
#include<sys/types.h>
#include<errno.h>
#include<signal.h>
#include <pthread.h>
#include<string.h>
#include<malloc.h>

 

void*fun1(void*)
{
while(1)
{
printf("1111");
}
}

void *fun2(void*)
{

while(1)
{
printf("2222");
}
}

//main函数里面的栈与线程中的栈是可以相互访问的。
int main(void)
{
pthread_attr_t attr;
pthread_t thr1,thr2 ;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr , PTHREAD_CREATE_DETACHED );//设置线程属性是可分离的。

if( pthread_create(&thr1 , &attr , func1 , NULL) )//线程函数func1
{
printf("thread1 error :%s\n" , strerror(errno));
}
if( pthread_create(&thr2 , NULL , func2 , &thr1 ) )//线程函数func2
{
printf("thread2 error :%s\n" , strerror(errno));
}

pthread_attr_destory(&attr);
pthread_join(thr1,NULL);//已经没用了。

return EXIT_SUCCESS;
}

////////////////////////////////////////////////////////////////////////////

 

posted on 2015-03-21 23:46  后进后退  阅读(140)  评论(0)    收藏  举报