使用场景:一个线程完成一个任务需要循环访问某函数3次,且在这3次之间不允许其他线程执行该函数
解释: 某函数会被多个线程调用,但是获取到函数使用权的线程会多次调用该函数且在多次调用期间不允许其他线程执行该函数
核心代码实现:
std::mutex mAcquireBufferMutex;
std::mutex mApplicantsMutex;
std::condition_variable mAcquireBufferCond;
static std::string caller(""); // 标记当前的占用者是谁
void run(std::string myName,bool last) // last表示这一次调用是不是该线程最后一次使用该代码段
{
std::unique_lock <std::mutex> lock(mAcquireBufferMutex);
if(caller != std::string("")){
while(caller != myName){
mAcquireBufferCond.wait(lock);
if(caller == std::string("")){
caller = myName;
break;
}
}
}else{
caller = myName;
}
/*
run函数真正需要执行的部分
*/
if(last){
caller = std::string(""); // 占用结束把标记量设为初始值
mAcquireBufferCond.notify_one();
}
}
可执行代码:
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <string>
#include <iostream>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <unistd.h>
using namespace std;
void run(std::string myName,bool last,int number);
void func1();
void func2();
void func3();
static std::string caller("");
std::mutex mAcquireBufferMutex;
std::mutex mApplicantsMutex;
std::condition_variable mAcquireBufferCond;
void run(std::string myName,bool last,int number)
{
std::unique_lock <std::mutex> lock(mAcquireBufferMutex);
if(caller != std::string("")){
while(caller != myName){
cout << myName.c_str() << " wait,number:"<< number << endl;
mAcquireBufferCond.wait(lock);
// std::unique_lock <std::mutex> lock(mApplicantsMutex); 如果使用notify_all();的话需要加锁再访问下面这个if判断
if(caller == std::string("")){
cout << myName.c_str() << " willRun,number:" <<number << endl;
caller = myName;
break;
}
}
}else{
caller = myName;
}
cout << myName.c_str() << " run,last:" << last <<" number:"<<number<<endl; // 用打印替代执行代码段
if(last){
caller = std::string(""); // 占用结束把标记量设为初始值
// mAcquireBufferCond.notify_all();
mAcquireBufferCond.notify_one();
}
}
int main()
{
thread thread1(&func1);
thread thread2(&func2);
thread thread3(&func3);
thread1.join();
thread2.join();
thread3.join();
return 0;
}
void func1()
{
int i = 0;
while(1)
{
++i;
run(std::string("func1"),((i%5) == 0),i); // (i%5)==0 用该语句为真表示整个线程中的一个小阶段
sleep(1); // 等待是为了更好的观察运行结果
}
}
void func2()
{
int i = 0;
while(1)
{
++i;
run(std::string("func2"),((i%5) == 0),i);
sleep(1);
}
}
void func3()
{
int i = 0;
while(1)
{
++i;
run(std::string("func3"),((i%5) == 0),i);
sleep(1);
}
}
linux上编译命令: g++ -o a.out threadTest.cpp -lpthread -std=c++11
执行结果:
############ notify_all() 场景
func1 run,last:0 number:1
func2 wait,number:1
func3 wait,number:1
func1 run,last:0 number:2
func1 run,last:0 number:3
func1 run,last:0 number:4
func1 run,last:1 number:5
func2 willRun,number:1
func2 run,last:0 number:1
func3 wait,number:1
func2 run,last:0 number:2
func1 wait,number:6
func2 run,last:0 number:3
func2 run,last:0 number:4
func2 run,last:1 number:5
func3 willRun,number:1
func3 run,last:0 number:1
func1 wait,number:6
func3 run,last:0 number:2
func2 wait,number:6
func3 run,last:0 number:3
func3 run,last:0 number:4
func3 run,last:1 number:5
func1 willRun,number:6
func1 run,last:0 number:6
func2 wait,number:6
func3 wait,number:6
func1 run,last:0 number:7
func1 run,last:0 number:8
func1 run,last:0 number:9
func1 run,last:1 number:10
func2 willRun,number:6
func2 run,last:0 number:6
func3 wait,number:6
func1 wait,number:11
func2 run,last:0 number:7
func2 run,last:0 number:8
func2 run,last:0 number:9
func2 run,last:1 number:10
func3 willRun,number:6
func3 run,last:0 number:6
func1 wait,number:11
func3 run,last:0 number:7
func2 wait,number:11
func3 run,last:0 number:8
func3 run,last:0 number:9
func3 run,last:1 number:10
func1 willRun,number:11
func1 run,last:0 number:11
func2 wait,number:11
func3 wait,number:11
func1 run,last:0 number:12
func1 run,last:0 number:13
func1 run,last:0 number:14
func1 run,last:1 number:15
func2 willRun,number:11
func2 run,last:0 number:11
func3 wait,number:11
func1 wait,number:16
func2 run,last:0 number:12
func2 run,last:0 number:13
func2 run,last:0 number:14
func2 run,last:1 number:15
func3 willRun,number:11
func3 run,last:0 number:11
func1 wait,number:16
################## notify_one() 情景
func1 run,last:0 number:1
func2 wait,number:1
func3 wait,number:1
func1 run,last:0 number:2
func1 run,last:0 number:3
func1 run,last:0 number:4
func1 run,last:1 number:5
func2 willRun,number:1
func2 run,last:0 number:1
func1 wait,number:6
func2 run,last:0 number:2
func2 run,last:0 number:3
func2 run,last:0 number:4
func2 run,last:1 number:5
func3 willRun,number:1
func3 run,last:0 number:1
func2 wait,number:6
func3 run,last:0 number:2
func3 run,last:0 number:3
func3 run,last:0 number:4
func3 run,last:1 number:5
func1 willRun,number:6
func1 run,last:0 number:6
func1 run,last:0 number:7
func3 wait,number:6
func1 run,last:0 number:8
func1 run,last:0 number:9
func1 run,last:1 number:10
func2 willRun,number:6
func2 run,last:0 number:6
func1 wait,number:11
func2 run,last:0 number:7
func2 run,last:0 number:8
func2 run,last:0 number:9
func2 run,last:1 number:10
func3 willRun,number:6
func3 run,last:0 number:6
func2 wait,number:11
func3 run,last:0 number:7
func3 run,last:0 number:8
func3 run,last:0 number:9
func3 run,last:1 number:10
func1 willRun,number:11
func1 run,last:0 number:11
func3 wait,number:11
func1 run,last:0 number:12
func1 run,last:0 number:13
func1 run,last:0 number:14
func1 run,last:1 number:15
func2 willRun,number:11
func2 run,last:0 number:11
func1 wait,number:16
func2 run,last:0 number:12
func2 run,last:0 number:13
func2 run,last:0 number:14
func2 run,last:1 number:15
func3 willRun,number:11
func3 run,last:0 number:11
func2 wait,number:16
func3 run,last:0 number:12
func3 run,last:0 number:13
func3 run,last:0 number:14
func3 run,last:1 number:15
func1 willRun,number:16
func1 run,last:0 number:16
func3 wait,number:16
func1 run,last:0 number:17
func1 run,last:0 number:18
func1 run,last:0 number:19