线程学习一(线程概念、创建、终止、收尸,栈的清理)

1、线程概念:

线程就是一个正在运行的函数
一个进程里面至少会有一个线程
多个线程的内存是共享的
posix线程是一套标准,不是实现
openmp线程也是一种标准

线程标识:pthread_t(类型不清楚,但是在Linux下是整形数)
相关函数介绍:
pthread_equal():
pthread_equal - compare thread IDs

	#include <pthread.h>

   	int pthread_equal(pthread_t t1, pthread_t t2);

  	Compile and link with -pthread.(编译或者链接的时候要加上-pthread)

写到makefile文件中
CFLAGS+=-pthread
LDFLAGS+=-pthread

pthread_self():(相当于进程中的get_pid)
pthread_self - obtain ID of the calling thread(获取当前线程的id

   	#include <pthread.h>

   	pthread_t pthread_self(void);

   	Compile and link with -pthread.

小的点:
ps axm(Linux可以看到进程的详细信息,可以看到–标识,就是线程)
ps ax -L(以Linux的形式查看进程和线程的关系)
Linux下以线程消耗进程号
会话是容器,承载进程组
进程组是容器,承载进程
进程是容器,承载线程
都有一种容器的概念
建议:不要把线程和信号大范围的混用

2、线程的创建

pthread_create():
pthread_create - create a new thread

	#include <pthread.h>
	
  	 int pthread_create(pthread_t *thread, const pthread_attr_t *attr(NULL表示默认),
                      void *(*start_routine) (void *)(函数,就是创建出的线程函数), void *arg)(函数的参数,若想传多个参数就使用结构体);
   	Compile and link with -pthread.

返回值
On success, pthread_create() returns 0; on error, it returns an error
number, and the contents of *thread are undefined.(只能用strerror来报错
例子:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

static void *func(void *p)
{

        puts("Thread is working!");
        return NULL;
}


int main()
{

        pthread_t tid;
        int err;

        puts("Beigin!");

        err=pthread_create(&tid,NULL,func,NULL);
        if(err)
        {
                fprintf(stderr,"pthread_create():%s\n",strerror(err));
                exit(1);
        }
        puts("End!");
        exit(0);
}

运行结果:
Beigin!
End!
看不到线程运行的原因:线程的调度取决于调度器的调度策略,在虚拟机里面不能多核运行线程来不及调度,进程就结束。(在不同的主机上运行结果不同)

线程终止

3种方式: 1)线程从启动例程返回,返回值就是线程的退出码。
		  2)线程被同一进程中的其他的线程取消
		  3)线程调用调用pthread_exit()函数(相当于进程阶段的exit()函数)

pthread_exit():
pthread_exit - terminate calling thread

 #include <pthread.h>

 	  void pthread_exit(void *retval);

   	Compile and link with -pthread.

例子:

static void *func(void *p)
{

        puts("Thread is working!");
        pthread_exit(NULL);//线程栈的清理用到

}

线程收尸

pthread_join();(相当于进程中的wait())
pthread_join - join with a terminated thread

#include <pthread.h>

 	  int pthread_join(pthread_t thread, void **retval);
第二项若是空,就表示只收尸,不关注状态
若是想把收尸的状态来加以查看的话,给一个void*类型变量的地址(一级指针的地址)
   	Compile and link with -pthread.

例子:
将上面的main函数中增加pthread_join()函数的使用

int main()
{

        pthread_t tid;
        int err;

        puts("Beigin!");

        err=pthread_create(&tid,NULL,func,NULL);
        if(err)
        {
                fprintf(stderr,"pthread_create():%s\n",strerror(err));
                exit(1);
        }
        pthread_join(tid,NULL);
        puts("End!");
        exit(0);
}

运行结果:(这个结果是一定的)
一定要等到线程运行完,才可以收尸,所以一定会运行线程。
Beigin!
Thread is working!
End!

栈的清理

pthread_cleanup_push():
pthread_cleanup_pop():(和钩子函数很像,或者可以想象栈的压和出)

pthread_cleanup_push():
pthread_cleanup_pop():
pthread_cleanup_push, pthread_cleanup_pop - push and pop thread cancel‐
lation clean-up handlers

#include <pthread.h>

   	void pthread_cleanup_push(void (*routine)(void *),
  	                           void *arg);
   	void pthread_cleanup_pop(int execute);
pop函数的参数若为真,说明函数要被调用,反之不被调用
   	Compile and link with -pthread.

例子:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

static void cleanup_func(void *p)
{
        puts(p);
}

static void *func(void *p)
{

        puts("Thread is working!");
        pthread_cleanup_push(cleanup_func,"cleanup:1");
        pthread_cleanup_push(cleanup_func,"cleanup:2");
        pthread_cleanup_push(cleanup_func,"cleanup:3");

        puts("push over");
	pthread_cleanup_pop(1);
       	pthread_cleanup_pop(1);
         	pthread_cleanup_pop(1);
      	pthread_exit(NULL);
}

int main
{
        pthread_t tid;
        int err;

        puts("Beign");

        err=pthread_create(&tid,NULL,func,NULL);
        if(err)
        {
                 fprintf(stderr,"pthread_create():%s\n",strerror(err));
                 exit(1);
        }
        pthread_join(tid,NULL);
        puts("End");
        exit(0);

}

运行结果:
Beign
Thread is working!
push over
cleanup:3
cleanup:2
cleanup:1
End

注意:push和pop一定是成对出现的,这两个不是函数,而是宏,可以用gcc .c文件 -E来验证,若是少了pop预处理的结果就会
少一个大括号匹配。若pop的参数为0,则表示只弹栈,而不去调用。比如上面的程序,若只有第一个pop参数是1,则结果只会
包含cleanup:3。pop可以放在任何的位置。若是放在pthread_exit后面,执行的时候,由于看不到后面的参数,默认都为1.

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值