最近在搞一个项目,需要给上层A提供一套c语言接口,共上层A的C++调用。而上层是并发的,在不同场景下,底层接口是不相同的,比如C与D,上层C++接口不能直接看到底层的不同实现,而是应该上层接口调用下层接口时,传入一个场景id给B,有B来负责依据id来调用C还是D。所以,由于A支持并发,所以B不能阻塞,同时A可以保证,C或者D只能同时被一个线程访问,由于不放心A,所以B自己对C与D做了加锁操作。使用C++ STL中的线程库实现。
【问题一】C++对象的析构
#include<iostream>
#include<thread>
using namespace std;
class A
{
public:
A() {
cout << "start" << endl;
}
~A() {
cout << "end" << endl;
}
};
void f(int id)
{
if (id == 0) {
// 在这里定义一个对象,出了{},则对象会被析构
A a;
}
else {
A a;
}
cout << "f end" << endl;
}
int main(int argc, int * argv[])
{
f(0);
system("pause");
}
结果如下:
可以看出,该对象的作用域为{},该问题是为了验证下面的lock_guard的能正确的加锁与解锁。
【二】实现上图A B C/D的架构
#include<iostream>
#include<thread>
#include<mutex>
using namespace std;
mutex mA;
mutex mB;
void f0()
{
cout << "enter f0" << endl;
for (int i = 0; i <5; i++)
{
cout << "i=" << i << endl;
}
}
void f1()
{
cout << "enter f1" << endl;
for (int i = 20; i < 25; i++)
{
cout << "i=" << i << endl;
}
}
void f(int id)
{
if (id == 0) {
//分场景加锁保护,防止f0被多线程访问
std::lock_guard<mutex> _1(mA);
f0();
}
else {
//分场景加锁保护
std::lock_guard<mutex> _1(mB);
f1();
}
cout << "f end" << endl;
}
int main(int argc, int * argv[])
{
//两个线程启动同一个函数,f内部实现场景分离
thread t1(f, 0);
thread t2(f, 1);
thread t3(f, 0);
thread t4(f, 1);
t1.join();
t2.join();
t3.join();
t4.join();
cout << "main" << endl;
system("pause");
}
结果如下:
可以看出,成功实现了不同场景下的并发处理,这里出现乱序的原因在于cout对象是唯一的,但是未加锁保护,导致多线程竞争访问。事实上,f0与f1不应该相同的资源,否则由于f0与f1未加锁,会导致资源竞争,这里仅仅是为了说明问题,所以使用的cout做打印。这里的关键在于这种场景下的架构与B的实现。