C++多线程问题 - 互斥是唯一的方法吗?

发布于 2024-08-19 03:53:26 字数 432 浏览 6 评论 0原文

我有一个计数器变量,它将被多个线程访问,这将增加/减少它。它不应该由多个线程同时更新。

我知道您可以创建一个互斥对象,必须在更改相关变量之前获取该对象。在这种情况下,临界区是不合适的,因为有多个函数可以更改相关变量。

还有另一个我可以在不使用互斥体的情况下做到这一点吗?使用互斥体确实会降低性能(请参阅 http://www.codeguru。 com/forum/showthread.php?t=333192)。我相信在Java中,你可以在变量声明中使用一个关键字来实现这一点(它被称为“同步”吗?),但是在C++中有这样的东西吗?

我知道 volatile 不是我要寻找的关键字。

非常感谢。

I have a counter variable which will be accessed by multiple threads which will increment/decrement it. It should not be updated by multiple threads at the same time.

I know that you can create a mutex object which has to be obtained before the variable in question can be changed. A critical section in this case is not appropriate because there are more than 1 function which can change the variable in question.

Is there another I can do this without using the mutex? Using a mutex does have a performance penalty (see http://www.codeguru.com/forum/showthread.php?t=333192). I believe that in Java, there is a key word you can use in the variable declaration to accomplish that (is it called "synchronized"?), but is there such a thing in C++ at all?

I know that volatile is not the keyword I am looking for.

Thank you very much.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

墨洒年华 2024-08-26 03:53:26

大多数处理器都有“原子”递增和递减指令 - 在很大程度上,它们是互斥体的方式是在机器级别实现的。

您可以在自己的代码中访问这些原子指令。 Windows 提供了 InterlockedIncrement() 函数,并且 glib 提供等效函数。在x86汇编语言中,可以直接使用LOCK CMPXCHG和kin。

C++ 对这些概念一无所知——你必须自己使用它们; C++ 中没有用于线程安全的神奇关键字。

请参阅原子指令

Most processors have 'atomic' increment and decrement instructions - in a large part, they are how mutexes are implemented at a machine level.

You can access these atomic instructions in your own code. Windows provides the InterlockedIncrement() function, and glib provides equivalents. In x86 assembly language, you can use LOCK CMPXCHG and kin directly.

C++ does not know anything about these concepts - you must use them yourself; there are no magic keywords for thread safety in C++.

See Atomic Instruction

故事还在继续 2024-08-26 03:53:26

虽然使用原子操作可能是最有效的,但事实上,在多个函数中使用原子操作并不妨碍在此代码或任何其他代码中使用关键部分 - 只需编写一个函数:

void IncDec( bool inc ) {
   EnterCritical Section( theCS );
   if ( inc ) {
     theVar++;
   }
   else {
     thevar--;
   }
   LeaveCriticalSection( theCS );
}

并从其他函数中调用它。

While the use of atomic operations is probably the most efficient, the fact that this is used in more than one function is no bar to using a critical section in this or any other code - simply write a function:

void IncDec( bool inc ) {
   EnterCritical Section( theCS );
   if ( inc ) {
     theVar++;
   }
   else {
     thevar--;
   }
   LeaveCriticalSection( theCS );
}

and cal it from your other functions.

醉生梦死 2024-08-26 03:53:26

从描述来看,听起来也许您只需要 InterlockedIncrement 和相关的减量函数。

编辑-这些是Windows功能......我没有停下来问哪个平台。

From the description, it sounds like maybe you only need InterlockedIncrement and the associated decrement function.

Edit - These are Windows functions ... I didn't stop to ask which platform.

亽野灬性zι浪 2024-08-26 03:53:26

本例中的关键部分是
不合适,因为还有更多
超过 1 个函数可以改变
有问题的变量。

这是使用关键部分的常见场景,您需要确保访问变量的每段代码在进入相同的关键部分(或互斥体,或使用任何保护)时都这样做。

A critical section in this case is
not appropriate because there are more
than 1 function which can change the
variable in question.

This is a common scenario where critical sections are used, you need to assure every piece of code that access the variables do so while entering the same critical section(or mutex, or whichever guarding is used).

感情洁癖 2024-08-26 03:53:26

在 Win32 IntelockedIncrement/IntelockedIncrement64 和相关操作编译为 x86 指令,允许对 32 或 64 位字(取决于您的体系结构)进行处理器级原子操作。这在简单计数器的情况下工作得很好,但如果您尝试将较大的结构与多个单词同步,这自然不会工作。

PS来自此处,您需要实现的相应asm这是在 x86 上运行的非 Win32 系统上的。

inline long InterlockedExchangeAdd( long* Addend, long Increment )
{
long ret;
__asm__ (
/* lock for SMP systems */
"lock\n\t"
"xaddl %0,(%1)"
:"=r" (ret)
:"r" (Addend), "0" (Increment)
:"memory" );
return ret;
}

inline long InterlockedIncrement( long* Addend )
{
return InterlockedExchangeAdd( Addend, 1 );
}

inline long InterlockedDecrement( long* Addend )
{
return InterlockedExchangeAdd( Addend, -1 );
}

In Win32 IntelockedIncrement/IntelockedIncrement64 and associated operations compile to x86 instructions that allow processor level atomic operations on 32 or 64 bit words (depending on your architecture). This works fine in the case of a simple counter, but naturally won't work if your trying to synchronize a larger structure with multiple words.

PS from here, the corresponding asm you would need to implement this on a non Win32 system running on an x86.

inline long InterlockedExchangeAdd( long* Addend, long Increment )
{
long ret;
__asm__ (
/* lock for SMP systems */
"lock\n\t"
"xaddl %0,(%1)"
:"=r" (ret)
:"r" (Addend), "0" (Increment)
:"memory" );
return ret;
}

inline long InterlockedIncrement( long* Addend )
{
return InterlockedExchangeAdd( Addend, 1 );
}

inline long InterlockedDecrement( long* Addend )
{
return InterlockedExchangeAdd( Addend, -1 );
}
郁金香雨 2024-08-26 03:53:26

您可以使用原子类型作为计数器变量 - 例如 sig_atomic_t (在 GNU libc 中)。那么就不需要同步,因为竞争条件不会发生,所以对该变量的操作保证是原子的。

You could use atomic type for the counter variable - like sig_atomic_t (in GNU libc). Then there is no need for synchronization, since a race condition cannot happen, the operation on this variable is guaranteed to be atomic.

︶葆Ⅱㄣ 2024-08-26 03:53:26

正如其他人提到的,当前的 C++ 标准中没有任何内容支持原子变量访问。但是,如果您要求 C++ 库支持(我不太清楚),则正在尝试模仿即将推出的 C++ 标准的原子支持 此处

As others have mentioned, there's nothing in the current C++ standard that supports atomic variable access. If you're asking for C++ library support however (not entirely clear to me), there's an attempt-in-progress to mimic the upcoming C++ standard's atomic support here.

太阳哥哥 2024-08-26 03:53:26

在这种情况下,临界区是不合适的,因为有多个函数可以更改相关变量。

如果您不使用临界区创建单个函数来修改变量,您如何知道您已找到该变量可能被访问的所有位置?

此外,您需要将变量声明为 易失性,只是确保您的编译器不会无意中优化对该变量的任何访问。

A critical section in this case is not appropriate because there are more than 1 function which can change the variable in question.

How will you know you have found all places the variable might be access if you don't create a single function using a critical section to modify it?

Additionally you will need to declare the variable volatile just make sure your compiler doesn't optimize any accesses to the variable inadvertently.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文