C++ 无等待的并发代码

C++ 无等待的并发代码,c++,multithreading,concurrency,C++,Multithreading,Concurrency,我正在考虑一种特定的同步原语,但我不知道这种同步被称为什么,或者类似的东西是否有效 因此,有一个变量(布尔值)基本上表示一个线程是否仍在处理内存块。在开始时,bool被设置为false,这意味着工作线程没有在内存块上工作。现在,主线程给工作线程一个“待办事项列表”,描述它应该如何处理该内存块。之后,它将布尔值的状态更改为true,以便工作线程知道现在允许它执行其工作。主线程现在可以继续自己的工作,并在某些位置检查工作线程现在是否已完成工作,例如,布尔值是否已再次设置为false。如果它仍然是tr

我正在考虑一种特定的同步原语,但我不知道这种同步被称为什么,或者类似的东西是否有效

因此,有一个变量(布尔值)基本上表示一个线程是否仍在处理内存块。在开始时,bool被设置为
false
,这意味着工作线程没有在内存块上工作。现在,主线程给工作线程一个“待办事项列表”,描述它应该如何处理该内存块。之后,它将布尔值的状态更改为
true
,以便工作线程知道现在允许它执行其工作。主线程现在可以继续自己的工作,并在某些位置检查工作线程现在是否已完成工作,例如,布尔值是否已再次设置为
false
。如果它仍然是true,则主线程只继续自己的工作,而不等待工作线程。如果布尔值为
false
,则主线程知道工作线程已完成,并开始处理内存块

所以布尔值只是在两个线程之间转移对内存块的所有权。如果一个线程当前没有该内存的所有权,它将继续自己的工作,并反复检查它现在是否再次拥有该内存的所有权。这样,所有线程都不会互相等待,并且可以继续自己的工作

这叫什么?这种行为是如何实现的

编辑:基本上它是一个互斥体。但它没有等待互斥锁再次解锁,而是继续/跳过关键代码

编辑:基本上它是一个互斥体。而不是等待互斥锁关闭 如果再次解锁,它将继续/跳过关键代码

它仍然是一个互斥体,只有“try”方法

<标准> C++中,我们讨论的是<代码> STD::MuteX::TyyLyObj/<代码>,它试图锁定互斥体,如果失败,它返回false并在

上移动
class unlocker{
 std::mutex& m_Parent;

public : 

unlocker(std::mutex& parent) : m_Parent(parent){}
~unlocker() {m_Parent.unlock(); }

};

std::mutex mtx;
if (mtx.try_lock()){
   unlocker unlock(mtx); // no, you can't use std::lock_guard/unique_lock here
   //success, mtx is free
} else{
  // do something else
}

在本机操作系统的代码上,根据所使用的操作系统,您具有类似的功能,如Unix上的
pthread\u mutex\u trylock
和Windows上的
tryIntercriticalSection
。不用说,标准互斥锁可能会在后台使用这些函数

如果主线程无法工作,您会怎么做

假设您不断检查并不断阅读
true
。最终,如果没有工作线程的结果,主线程将无法继续。由于您没有更多的工作要做,现在剩下的唯一一件事就是反复检查标志的值,这浪费了其他线程可以用来做有用工作的CPU资源

一般来说,这不是你想要的。相反,您希望操作系统将主线程置于睡眠状态,并且仅在工作线程完成处理后将其唤醒。现代操作系统附带的各种锁和信号灯都是这样工作的。在内存中有一些标志指示谁拥有锁,但也有一些围绕它的逻辑,确保操作系统不会调度除了等待锁准备就绪之外无事可做的线程

也就是说,在某些情况下,这不是你想要的。如果您充分肯定不会遇到一个线程在锁上旋转的情况,并且希望节省操作系统锁带来的开销,那么只需检查您描述的标志可能是一个可行的选择


请注意,像这样的低级工具应该为特殊情况保留,而不是工具箱中的第一个工具。它很容易以一个不正确的算法或者一个没有你想象的那么高效的实现而告终。如果你决定沿着这条路走下去,准备做一些严肃的工作,让它按预期工作。

这可能是
std::future
和/或
std::packaged_task
的好例子。在做工作的同时定期检查一些外部事件被称为“轮询”。它可以用一个原子变量来实现。这通常不是一个好主意。你能解释一下原因吗?因为你经常投票会浪费资源,而当你投票不够频繁时,你会不必要地等待。与检查事件相比,更喜欢等待事件,因为等待没有这些缺点。这是一种有效的方法吗?我需要问——在并发编程中,看似简单的方法在大多数情况下都是错误的。如果这样做是正确的,那取决于应用程序。通常,更好的选择是通常减少争用,或者首先切换到无锁数据类型。但不管怎样,你似乎对表现感到困扰。我认为应该首先证明,争论是他的瓶颈。
try\u lock
的问题在于它不可靠。互斥可以很好地保护资源不受并发访问,但在发送信号方面做得相当糟糕。在C++线程库中,如果您需要信令,您可能需要将来(一次性信号)或条件变量(可重用信号)。@ DavidHaim可以使用<代码> STD::UnQuyYOLD > <代码> STD::ApvttFux标签。代码>标准::唯一锁定(mtx,标准::采用锁定)更好的方法是使用
std::try_to_lock
标记:
if(auto l=std::unique_lock(mtx,std::try_to_lock)){…}