一、线程结束方式
1.pthread_exit()
2.main函数中的return
3.pthread_cancel 线程的取消
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
void * do_something(void *arg)
{
static int a = 10;
while (1)
{
printf("------do_something ---- \n");
sleep(1);
}
return &a;
}
int main(int argc, const char *argv[])
{
pthread_t tid;
int ret = pthread_create(&tid,NULL,do_something,NULL);
if (ret != 0)
{
errno = ret;
perror("pthread_create fail");
return -1;
}
sleep(3);
pthread_cancel(tid);
printf("----cancel thread----\n");
pthread_exit(NULL);
return 0;
}
4.任何一个线程调用exit,或主函数结束return都会造成进程结束。
pthread_cancel(pthread_t thread)
参数表示tid码。
功能:发送取消的请求 成功返回0,失败返回错误码
二、线程资源回收
函数:pthread_detach();
int pthread_detach(pthread_t thread);
功能:分离线程
参数:thread 要分离的线程的tid
返回值:成功 0,失败 错误码
pthread_join //需要自己回收 ---线程的属性 (可结合性) --- 一般是子线程 在较短时间内运行完
这种用于 ,线程任务较短,主线程需要关心子线程状态
pthread_detach //可分离属性 ---子线程运行很久才结束 --- 设置分离属性,子程序执行任务较长,主线程也不需要关心子线程状态
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
void * do_something(void *arg)
{
static int a = 10;
//线程的任务函数
printf("------do_something ---- \n");
//pthread_exit(NULL);
pthread_exit(&a);
//pthread_exit((void *)a);
}
int main(int argc, const char *argv[])
{
pthread_t tid;
int ret = pthread_create(&tid,NULL,do_something,NULL);
if (ret != 0)
{
errno = ret;
perror("pthread_create fail");
return -1;
}
pthread_detach(tid);
void *retval;
if (pthread_join(tid,&retval) != 0)
{
perror("pthread_join fail");
return -1;
}
printf("---- main----%d\n",*(int *)retval);
//pthread_exit(NULL);
return 0;
}
三、锁
共享资源: 临界资源
临界区 : 访问共享资源(临界资源)那段代码
互斥锁:互斥 排他性 --- 要么不访问 要访问就是一次完整操作 (原子操作)
定义互斥锁 ==》初始化锁 ==》加锁 ==》解锁 ==》销毁
定义互斥锁:pthread_mutex_t mutex;
初始化锁:pthread_mutex_init();
加锁:pthread_mutex_lock();
解锁 :pthread_mutex_unlock();
销毁:pthread_mutex_destroy();
pthread_mutex_init()
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
参数:mutex //就是要初始化的 互斥锁变量
attr //属性 NULL 默认属性 --- 普通锁 ,读写锁
int pthread_mutex_lock(pthread_mutex_t *mutex); 上锁
int pthread_mutex_trylock(pthread_mutex_t *mutex); 尝试获取锁,
int pthread_mutex_unlock(pthread_mutex_t *mutex); 解锁
参数:mutex //要操作的那把锁
int pthread_mutex_destroy(pthread_mutex_t *mutex); //用完之后锁要销毁
锁是一种线程间 同步机制
互斥锁 -- 保证线程对于共享资源的排他性访问 。 保证每个线程访问时的原子性操作
操作 :初始化 一把锁 (动态初始化 pthread_mutex_init,静态初始化 用初始化的宏)---加锁---解锁---销毁。
#include <head.h>
//静态初始化
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
char buf[20];
void * doSth1(void *arg)
{
while (1)
{
pthread_mutex_lock(&mutex);
int i = 0;
for (i = 0; i < 10; ++i)
{
buf[i] = 'a' + i;
}
printf("Sth1 buf = %s\n",buf);
pthread_mutex_unlock(&mutex);
}
}
void * doSth2(void *arg)
{
while (1)
{
pthread_mutex_lock(&mutex);
int i = 0;
for (i = 0; i < 10; ++i)
{
buf[i] = '0' + i;
}
printf("Sth2 buf = %s\n",buf);
pthread_mutex_unlock(&mutex);
}
}
int main(int argc, const char *argv[])
{
pthread_t tid[2];
int ret = pthread_create(&tid[0],NULL,doSth1,NULL);
if (ret != 0)
handle_error_en(ret,"pthread_create fail");
ret = pthread_create(&tid[1],NULL,doSth2,NULL);
if (ret != 0)
handle_error_en(ret,"pthread_create fail");
pthread_join(tid[0],NULL);
pthread_join(tid[1],NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
四、死锁
1.什么是死锁
死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象。
当多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前
进,这种情况就是死锁。
很显然,如果没有外力的作用,那么死锁涉及到的各个进程都将永远处于封锁状态。
2.死锁产生的四个必要条件:四者缺一不可,均需满足
(1)互斥条件:进程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。
(2)不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放(只能是主动释放)。
(3)请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。
(4)循环等待条件:存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被链中下一个进程所请求。注:发生死锁一定有循环等待,但是循环等待不一定是死锁。
3.死锁的处理策略
(1)预防死锁。破坏死锁产生的四个必要条件中的一个或几个,
(2)避免死锁。用某种方法防止系统进入不安全状态,从而避免死锁(银行家算法)
(3)死锁的检测和解除。允许死锁的发生,不过操作系统会负责检测出死锁的发生,然后采取某种措施解除死锁。
4.什么时候会发生死锁
(1)对系统资源的竞争。各进程对不可剥夺的资源(如打印机)的竞争可能引起死锁,对可剥夺的资源(CPU)的竞争是不会引起死锁的。
(2)进程推进顺序非法。请求和释放资源的顺序不当,也同样会导致死锁。例如,并发执行的进程P1P2分别申请并占有了资源 R1、R2,之后进程P1又紧接着申请资源R2,而进程P2又申请资源R1,两者会因为申请的资源被对方占有而阻塞,从而发生死锁。
(3)信号量的使用不当也会造成死锁。如生产者-消费者问题中,如果实现互斥的P操作在实现同步的P操作之前,就有可能导致死锁。(可以把互斥信号量、同步信号量也看做是一种抽象的系统资源)
总之,对不可剥夺资源的不合理分配,可能导致死锁。