线程间互斥相关概念
临界资源:多线程执行流共享的资源就叫做临界资源
临界区:每个线程内部,访问临界资源的代码,就叫做临界区
互斥:任何时刻,互斥保证有且只有一个执行流进入临界区,访问临界资源,通常对临界资源起保护作用
原子性:不会被任何调度机制打断的操作,该操作只有两态,要么完成,要么未完成,没有正在做的概念
引入锁---模拟一轮抢票
使用多线程,并发的进行抢票
下面的代码很容易看懂的
#include<iostream>
#include<vector>
#include<string>
#include<unistd.h>
#include<pthread.h>
using namespace std;
#define NUM 4
int tickets=3000;
class PtData
{
public:
PtData(int number)
{
_ptname="thread-"+to_string(number);
}
public:
string _ptname;
};
void* GetTicket(void* args)//模拟一轮抢票
{
PtData* td=static_cast<PtData*>(args);
const char* name=td->_ptname.c_str();
while(true)
{
if(tickets>0)
{
usleep(1000);
printf("who=%s,get a ticket:%d \n",name,tickets);
tickets--;
}
else break;
}
printf("%s....quit\n",name);
return nullptr;
}
int main()
{
//创建多线程
vector<pthread_t> tids;
vector<PtData*> pds;
for(int i=1;i<=NUM;i++)
{
pthread_t tid;
PtData* td=new PtData(i);
pds.push_back(td);
pthread_create(&tid,nullptr,GetTicket,td);
tids.push_back(tid);
}
for(auto tid:tids)
{
pthread_join(tid,nullptr);
}
for(auto pd:pds)
{
delete pd;
}
return 0;
}
截取了结果的最后面,发现竟然有线程抢到了负数票,但是在我们的理解当中是不可能的啊,怎么回事呢?tickets是全局变量,它被多个线程并发访问,就会导致数据不一致问题
对一个全局变量进行--操作是否安全呢?从结果看不安全
对tickets--,一条C语句,会被转为三条汇编语句
1.先将tickets读入到CPU的寄存器中
2.CPU内部进行--操作
3.将计算结果写回内存
总的来说,由于线程的并发访问,线程会被切走,对全局变量计算操作汇编语句有多条,当某个线程正在执行某条的时候都有可能被切走,导致还没计算完,就有线程来访问,就会导致数据不一致问题,对全局变量计算不是原子的(原子就是做一件事,要么做完,要么不做,没有正在做的概念)
要解决以上问题,需要做到三点:
代码必须要有互斥行为:当代码进入临界区执行时,不允许其他线程进入该临界区。
如果多个线程同时要求执行临界区的代码,并且临界区没有线程在执行,那么只能允许一个线程进入该临界区。
如果线程不在临界区中执行,那么该线程不能阻止其他线程进入临界区。
要做到这三点&#