在这种情况下,有什么正确的方法可以实现锁定吗?

Any proper way to achieve locks in a situation like this?

本文关键字:实现 锁定 方法 这种情况下 什么      更新时间:2023-10-16

我有一个对象数组,我想在线程中操作,但有时我也希望能够访问。这感觉像是实现我的目标的黑客方法,但是有没有更好的方法来做这样的事情?:
*基本目标是有2把锁。一个允许所有单个线程并发工作,同时阻止来自数组的访问,直到它们全部完成,另一个允许关闭来自线程的访问,以确保在函数运行时没有对象被其他线程接触。

atomic<int> inThreadCount;
atomic<int> arrayLock;
map<string, MyObj*> myMap;
mutex mu1;
class MyObj{
mutex mu2;
int myInt;
public: 
void update(bool shouldLowerCount){
mu2.lock();
myInt++;
if (shouldLowerCount)
inThreadCount--;
mu2.unlock();
}
}
//Some operation that requires all threads to finish first
//and doesn't allow threads to access the objects while running
void GetSnapshot(){ 
mu1.lock();
arrayLock++;
while (inThreadCount > 0)
Sleep(0);
map<string, MyObj *>::iterator it = myMap.begin();
auto t = time(nullptr);
auto tm = *localtime(&t);
cout << put_time(&tm, "%d-%m-%Y %H-%M-%S") << endl;
for( ; it != myMap.end(); ++it){
cout << it->first << ":" << it->second->counter);
}
arrayLock--;
mu1.unlock();
}
void updateObject(MyObj* myObj){
while (arrayLock > 0)
Sleep(0);
inThreadCount++;
async(std::launch::async, myObj->update(true));
}

PS,我意识到在 Sleep(( 和 arrayLock/inThreadCount++ 之间有一个很小的错误机会窗口。这是我想解决的问题的一部分!

我认为您要求共享互斥锁。 共享互斥锁(或读写互斥锁(允许多个线程并行锁定对象,同时还允许一次一个线程以独占方式锁定对象。

简单来说,如果线程请求共享访问,则授予共享访问权限,除非线程以独占方式保存对象。当对象未由任何其他线程持有(共享或独占(时,将授予线程独占性。

它的常见用途是读写独占性。请参阅对读取的共享访问权限和对写入的独占访问权限。这是有效的,因为只有当两个或多个线程访问相同的数据并且其中至少一个是写入操作时,才会发生数据争用。多个阅读器不是数据竞赛。

与独占锁相比,实现共享锁通常有开销,并且该模型通常仅在有"许多"读取器的情况下提供帮助 读取"频繁"和写入操作"不频繁"。"多"、"频繁"和"不频繁"的含义取决于平台和手头的问题。

这正是共享互斥锁的用途。 C++17 开箱即用std::shared_mutex支持这一点,但我注意到这个问题被标记为 C++11。

一些实现已经提供了一段时间(这是一个经典的锁定策略( 或者你可以试试boost::shared_mutex<>.

注意:共享锁的挑战之一是避免写入器上的实时锁定。 如果有很多读者经常阅读,那么作者很容易无限期地被"锁定"并且永远不会进步(或进展非常缓慢(。 一个好的共享锁将为作者最终轮到一个提供一些保证。这可能是绝对优先级(不允许在线程开始后启动编写器