1.线程的概念
①线程就是一个正在运行的程序
②是main线程在运行,不是主线程,没有主次之分,线程之间是平等的关系
③多个线程共享内存,在同一块内存空间内
④他们之间的通讯会很简单,他们打开的文件描述符都一模一样的,或者一个全局变量等等
⑤从并发角度来看, 线程比进程简单,线程是先标准化,才被实现出来
⑥POSIX线程是一个标准 pthread_t 类型
⑦CPU的调度是以线程为单位的
⑧Compile and link with -pthread
2.
你的会话是一个容器,用来容纳进程组,你的进程组是一个容器,用来容纳进程,你的进程是一个容器,用来容纳线程
3.pthread_equal
比较两个线程是否相等 各家对pthread_t这种类型的实现不同
NAME
pthread_equal - compare thread IDs
SYNOPSIS
#include <pthread.h>
int pthread_equal(pthread_t t1, pthread_t t2);
Compile and link with -pthread.
DESCRIPTION
The pthread_equal() function compares two thread identifiers.
4.pthread_self
返回自己的线程id
NAME
pthread_self - obtain ID of the calling thread
SYNOPSIS
#include <pthread.h>
pthread_t pthread_self(void);
Compile and link with -pthread.
5.pthread_create
NAME
pthread_create - create a new thread
SYNOPSIS
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
on error, it returns an error number
第一个参数是回填的线程id
第二个参数是创建线程的属性,NULL 可以解决80%的问题
第三个参数是一个函数指针(我们前面提到 一个线程就是一个跑的函数 )
第四个参数是函数的参数
void * 作为参数 可以传递任何想传递的参数,可以封装成任意的结构体,传过去一个地址就ok
不设置errno
6.一个demo
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void * Fun(void *p )
{
puts("Thread Working!");
return NULL;
}
int main()
{
pthread_t tid;
int err;
puts("Begin");
err = pthread_create(&tid, NULL, Fun, NULL);
if(err)
{
fprintf(stderr, "pthCreate %s\n", strerror(err));
exit(1);
}
puts("End");
return 0;
}
感到很奇怪,为什么线程没有被执行呢?
原因是因为exit 八种进程终止的方式!
进程已经被杀死了
最简单的 你加一个sleep
7.线程的终止
①线程简单的从启动例程退出,返回值就是他的退出码
②线程调用pthread_exit();
③线程被同一进程中的其他线程取消
8.pthread_exit
NAME
pthread_exit - terminate calling thread
SYNOPSIS
#include <pthread.h>
void pthread_exit(void *retval);
void * Fun(void *p )
{
puts("Thread Working!");
//return NULL;
pthread_exit(NULL);
}
9.pthread_join
用来等待一个线程的结束,并进行资源的回收
NAME
pthread_join - join with a terminated thread
SYNOPSIS
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
相当于wait,但是wait收尸 收回来的是谁不重要
void * * retval收尸的线程返回的状态
int main()
{
pthread_t tid;
int err;
puts("Begin");
err = pthread_create(&tid, NULL, Fun, NULL);
if(err)
{
fprintf(stderr, "pthCreate %s\n", strerror(err));
exit(1);
}
pthread_join(tid, NULL);
puts("End");
return 0;
}
10栈的清理
在进程中我们使用钩子函数,当程序正常退出的时候,来执行我们希望的一些操作,线程中也有,只不过取钩子的过程,必须自己来做
- push and pop thread cancellation clean-up handlers
SYNOPSIS
#include <pthread.h>
void pthread_cleanup_push(void (*routine)(void *),
void *arg);
void pthread_cleanup_pop(int execute);
由于是宏实现的,所以二者必须成对出现
11.一个demo
void CleanupFun(void *pStr)
{
puts(pStr);
}
void * Fun(void *p )
{
puts("Thread Working!");
pthread_cleanup_push(CleanupFun, "Hello1");
pthread_cleanup_push(CleanupFun, "Hello2");
pthread_cleanup_push(CleanupFun, "Hello3");
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("Begin");
err = pthread_create(&tid, NULL, Fun, NULL);
if(err)
{
fprintf(stderr, "pthCreate %s\n", strerror(err));
exit(1);
}
pthread_join(tid, NULL);
puts("End");
exit(0);
}
void * Fun(void *p )
{
puts("Thread Working!");
pthread_cleanup_push(CleanupFun, "Hello1");
pthread_cleanup_push(CleanupFun, "Hello2");
pthread_cleanup_push(CleanupFun, "Hello3");
puts("push over");
pthread_exit(NULL);
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
}
我把线程退出放到 pop之前,并且传参是0,但是还是被调用了,由于执行不到后面,所以都认为传参是1