线程退出方式总结:
1.pthread_exit; void pthread_exit(void *retval);
传的是退出状态值对应的地址
2.执行函数中return
3.pthread_cancel // int pthread_cancel(pthread_t thread);
4.在任何一个线程中调用了exit
#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);
}
//pthread_exit(&a); //
return &a; //线程执行函数中return
}
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");
#if 0
void *retval;
pthread_join(tid,&retval);
printf("---- main----%d\n",*(int *)retval);
#endif
pthread_exit(NULL);
return 0;
}
线程资源回收:
1.pthread_join //需要自己回收 线程的属性(可结合性)--一般是子线程在较短时间内 主线程需要关系子线程状态
2.pthread_detach //可分离属性:子线程运行很久才结束。主线程不需要关系子线程状态
int pthread_detach(pthread_t thread);
功能:分离线程
参数:要分离的线程tid
返回值:成功0;失败错误码。
线程和进程的对比
1.线程 CPU执行的最小单位
进程 资源分配和任务调度基本单位
2.安全性
线程
好处:共享了进程的数据空间 ,共享数据方面 方便
缺点: 安全性不好会带来资源竞争
进程 进程空间相互独立
优点:
安全性好
缺点:
进程间共享数据不方便 //进程间通信 (管道,信号,共享内存)
主要区别:
(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行
(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.
(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。
锁:
机制:互斥锁
互斥:要么不访问,要访问就是一次完整操作(原子操作)
定义锁 pthread_mutex_t mutex;
初始化锁 pthread_mutex_init;
加锁 int pthread_mutex_lock(pthread_mutex_t *mutex);
解锁 int pthread_mutex_unlock(pthread_mutex_t *mutex);
销毁锁 pthread_mutex_destory(pthread_mutex_t *mutex);
teylock 和 lock的区别:
#include <pthread.h>
#include <stdio.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int counter = 0;
void* increment_counter(void* arg) {
for (int i = 0; i < 10000; ++i) {
// 锁定互斥锁,等待直到获得锁
pthread_mutex_lock(&mutex);
// 安全地更新计数器
counter++;
printf("Counter is now %d\n", counter);
// 释放互斥锁
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main() {
pthread_t t1, t2;
// 创建两个线程
pthread_create(&t1, NULL, increment_counter, NULL);
pthread_create(&t2, NULL, increment_counter, NULL);
// 等待线程结束
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("Final counter value is %d\n", counter);
return 0;
}
#include <pthread.h>
#include <stdio.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int counter = 0;
void* increment_counter_trylock(void* arg) {
for (int i = 0; i < 10000; ++i) {
// 尝试锁定互斥锁
if (pthread_mutex_trylock(&mutex) == 0) {
// 成功获取锁,更新计数器
counter++;
printf("Counter is now %d\n", counter);
// 释放互斥锁
pthread_mutex_unlock(&mutex);
} else {
// 未能获取锁,可以做一些其他的事情或者简单地重试
// 这里我们选择简单的重试
continue;
}
}
return NULL;
}
int main() {
pthread_t t1, t2;
// 创建两个线程
pthread_create(&t1, NULL, increment_counter_trylock, NULL);
pthread_create(&t2, NULL, increment_counter_trylock, NULL);
// 等待线程结束
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("Final counter value is %d\n", counter);
return 0;
}
死锁
线程间的顺序问题: 同步操作
信号量:实现一种可以让线程间有序访问临界资源的方式, 可以顺序操作的一把锁