抢票的例子
竞争过程
进程A被切走
进程B被切走
结论:
互斥
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
mutex
: 指向要初始化的互斥锁的指针。attr
: 用于设置互斥锁属性的指针,通常可以传入NULL
以使用默认属性。
锁的本质
加锁
解锁
线程安全与重入
死锁
线程同步
生产消费模型
例子
条件变量
demo
#include<iostream>
#include<string>
#include<pthread.h>
#include<unistd.h>
int tickets=1000;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
void *start_routine(void* args){
std::string name=static_cast<const char*>(args);
while(true){
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
std::cout<<name<<"->"<<tickets<<std::endl;
tickets--;
pthread_mutex_unlock(&mutex);
}
return nullptr;
}
int main(){
const int num=5;
pthread_t tid[num]{};
for(int i=0;i<num;i++){
char *name=new char[64];
snprintf(name,sizeof(name),"thread %d",i+1);
pthread_create(tid+i,nullptr,start_routine,name);
}
while(true){
std::cout<<"main thread weak up"<<std::endl;
pthread_cond_signal(&cond);
sleep(1);
}
for(int i=0;i<num;i++){
pthread_join(tid[i],nullptr);
}
return 0;
}
信号量
常用函数
环形队列
环形队列代码
#include"RingQueue.hpp"
#include<unistd.h>
#include<pthread.h>
#include<random>
#include<iostream>
void *ProductorRoutine(void* rq){
RingQueue<int> *ringqueue=static_cast<RingQueue<int>*>(rq);
while(true){
int data=rand()%10+1;
ringqueue->Push(data);
std::cout<<"生产完成 生产的数据是:"<<data<<std::endl;
sleep(1);
}
}
void *ConsumerRoutine(void *rq){
RingQueue<int> *ringqueue=static_cast<RingQueue<int>*>(rq);
while(true){
int data;
ringqueue->Pop(data);
std::cout<<"消费完成 消费数据是:"<<data<<std::endl;
sleep(1);
}
}
int main(){
srand((unsigned int)time(nullptr)^getpid()^pthread_self());
RingQueue<int> *rq=new RingQueue<int>();
pthread_t p,c;
pthread_create(&p,nullptr,ProductorRoutine,rq);
pthread_create(&c,nullptr,ConsumerRoutine,rq);
pthread_join(p,nullptr);
pthread_join(c,nullptr);
}
#include<semaphore.h>
#include<vector>
#include<cassert>
#include<ctime>
#include<sys/types.h>
static const int gcap=5;
template<class T>
class RingQueue{
public:
void P(sem_t &sem){
int n=sem_wait(&sem);
assert(n==0);
(void)n;
}
void V(sem_t &sem){
int n=sem_post(&sem);
assert(n==0);
(void)n;
}
public:
RingQueue(const int &cap=gcap):_q(cap),_cap(cap){
int n=sem_init(&_spaceSem,0,_cap);
assert(n==0);
n=sem_init(&_dataSem,0,0);
assert(n==0);
productorStep=ConsumerStep=0;
}
void Push(const T &in){
P(_spaceSem);
_q[productorStep++]=in;
productorStep%=_cap;
V(_dataSem);
}
void Pop(T &out){
P(_dataSem);
out=_q[ConsumerStep++];
ConsumerStep%=_cap;
V(_spaceSem);
}
~RingQueue(){
sem_destroy(&_spaceSem);
sem_destroy(&_dataSem);
}
private:
std::vector<T> _q;
int _cap;
sem_t _spaceSem; //生产者 空间资源
sem_t _dataSem; //消费者 数据资源
int productorStep;
int ConsumerStep;
};