线程同步
就是线程间相互协同(协助),相互配合完成某个工作.根本在于协同步调,按照预定先后次序运行
其实就是一个线程返回,另一个线程开始.不然会造成数据混乱
数据混乱原因
线程间资源共享(当然独享的不会)
线程间调度时随机的
线程间缺少必要的同步机制(协同,步调)
共享和随机不能改变,只能通过协同来着手,使线程出现互斥
互斥锁mutex
公共数据时,锁会阻塞,哪个线程有锁哪个线程执行
但是这个锁叫建议锁,没有强制性.也就是说可以不拿锁,直接去访问数据.
只能程序员来指定在访问公共数据时,先去拿锁在访问
死锁
对一个锁反复加锁,(失败会阻塞,阻塞等待得到锁的解锁,而此时加锁的是自己,导致没办法后续解锁)
两个线程,各有一把锁,相互请求另一把(这样会使两个线程相互阻塞)
读写锁rwlock
一把锁两种状态
读写锁特性
写独占,读共享
读写并行阻塞,写锁优先级高
写模式加锁,解锁前对该加锁线程读写都会阻塞
读模式加锁,线程可以以读模式加锁,写模式加锁会阻塞
读写锁在读大于写的时候非常适用,但是这个东西使用确实不多,而且复杂
互斥锁的步骤
头文件
都是 #include <pthread.h>
返回值
都是 成功返回0,失败返回errno
pthread_mutex_t mutex(创建锁)
pthread_mutex_t是一个结构体
pthread_mutex_t mutex只取0, 1,初始为1,加锁为0(阻塞),解锁为1(唤醒阻塞)(这个不对,只是可以这样理解)
pthread_mutex_init(初始化锁)
原型
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
参数
restrict(C99中的) 是一个关键字,表示除了这个当前指针其他方式不能修改内容
attr状态,一般传null
pthread_mutex_lock(加锁)
原型
int pthread_mutex_lock(pthread_mutex_t *mutex);
pthread_mutex_unlock(解锁)
原型
int pthread_mutex_unlock(pthread_mutex_t *mutex);
pthread_mutex_destroy(销毁锁)
原型
int pthread_mutex_destroy(pthread_mutex_t *mutex);
#include <iostream>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
using namespace std;
pthread_mutex_t mutex; // 创建锁
void *func(void *argv)
{
int ret;
while (true)
{
ret = pthread_mutex_lock(&mutex); // 加锁
if (ret)
{
// 对了,用perror这个错误号显示不出来具体细节
// 需要使用最开始的strerr() 在string.h中
// 不过无所谓,这个东西就是为了方便我们调试嘛,只要知道具体哪里的问题对于我们来说已经足够
// 即使cout打印也一样
perror("ret = pthread_mutex_lock(&mutex)");
exit(1);
}
cout << "linux";
sleep(1);
cout << "C++" << endl;
ret = pthread_mutex_unlock(&mutex);
if (ret)
{
cout << "ret = pthread_mutex_unlock(&mutex);" << strerror(ret) << endl;
exit(1);
}
sleep(1); // 这个只是为了让效果,不然一个线程会占用CPU很长时间
}
}
int main(int argc, char **argv)
{
pthread_t tid;
int ret = pthread_mutex_init(&mutex, nullptr); // 初始化锁
if (ret)
{
perror("int ret = pthread_mutex_init(mutex,nullptr);");
exit(1);
}
ret = pthread_create(&tid, nullptr, func, nullptr); // 创建线程
if (ret)
{
perror("ret = pthread_create(&tid,nullptr,func,nullptr)");
exit(1);
}
while (true)
{
ret = pthread_mutex_lock(&mutex); // 加锁
if (ret)
{
// 对了,