线程
咱们先搞懂啥叫进程,进程就是程序跑起来之后,操作系统给它分配一整套完整资源,内存啥的全是它自己独占。
那线程就是进程里面最小干活单位,又叫轻量级进程。
一个进程里面可以开好多个线程,同一个进程里的所有线程,堆内存、全局变量、静态变量这些东西全部是共享的,只有栈内存每个线程是自己独一份。栈用来存局部变量,所以各个线程的局部变量互不干扰,全局变量大家抢着用。
进程和线程核心区别
-
进程:操作系统分配资源的最小单元,每个进程拥有独立整套虚拟内存,进程和进程之间完全隔离。一个进程崩掉,不会影响别的进程。开销大,创建销毁慢。
-
线程:操作系统CPU调度干活的最小单元。线程没有自己独立资源,寄生在进程里面。只要任意一个线程崩溃,整个所属进程直接全部挂掉。开销很小,创建、切换、销毁速度飞快。
线程相关函数
pthread_create 创建线程
功能:在咱们现有程序里面,生成一个新线程出来干活。
参数:
-
第一个参数:存放新线程ID的变量地址;
-
第二个参数线程属性,一般直接填NULL,用系统默认;
-
第三个参数是函数指针,就是新线程要去跑的那个函数;
-
第四个参数,传给线程函数的参数,没参数就NULL。
返回值:成功返回0,失败返回错误数字。
pthread_exit 线程退出
在线程的函数里面调用这个,代表当前这个线程结束。注意!这个只是结束线程,不会把整个进程干掉。如果在主线程main里面调用pthread_exit,主线程退出去,别的子线程还能继续跑。
pthread_join 回收线程
线程干完活退出之后,资源不会自动清理,就会产生僵尸线程,占内存。
pthread_join(线程id, &返回值变量)
作用:等着目标线程结束,然后回收它占的资源。这个函数是阻塞的,如果线程还没跑完,程序就卡在这原地等,直到线程结束才往下走。
线程分离属性 pthread_attr_setdetachstate
如果不想手动调用pthread_join回收,就可以把线程设置成分离态。
分离态的线程:线程一执行结束,操作系统自动帮它清理全部资源,不用join。
步骤:先初始化属性,设置成分离状态,创建线程的时候把属性传进去。
多线程会出现的问题:资源竞争
举个例子:多个线程同时读写同一个全局变量。
线程A读到变量是10,还没来得及写回去,CPU切到线程B,B也读到10,两个线程都做+1操作,最后结果本该12,实际变成11,数据就错了,这叫竞态条件。
解决办法就是互斥锁。
互斥锁pthread_mutex
-
pthread_mutex_init:初始化一把互斥锁;也可以直接写 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 静态初始化。
-
pthread_mutex_lock:加锁。如果锁现在被别人拿着,当前线程就卡在这睡觉,等锁被释放。
-
pthread_mutex_unlock:解锁,把锁交出去,别的等待的线程就可以拿到锁。
-
pthread_mutex_destroy:不用锁了,销毁释放资源。