Java C++;多线程问题-互斥是唯一的方法吗?
我有一个计数器变量,它将被多个线程访问,这些线程将递增/递减它。它不应该由多个线程同时更新 我知道,您可以创建一个互斥对象,该对象必须在更改相关变量之前获得。在这种情况下,临界截面是不合适的,因为有不止一个函数可以改变所讨论的变量 有没有其他我可以不使用互斥的方法来实现这一点?使用互斥锁确实会降低性能(请参阅)。我相信在java中,有一个关键字可以在变量声明中使用来完成(它被称为“同步”),但是C++中是否有这样的事情? 我知道volatile不是我要找的关键词Java C++;多线程问题-互斥是唯一的方法吗?,java,c++,synchronization,multithreading,synchronisation,Java,C++,Synchronization,Multithreading,Synchronisation,我有一个计数器变量,它将被多个线程访问,这些线程将递增/递减它。它不应该由多个线程同时更新 我知道,您可以创建一个互斥对象,该对象必须在更改相关变量之前获得。在这种情况下,临界截面是不合适的,因为有不止一个函数可以改变所讨论的变量 有没有其他我可以不使用互斥的方法来实现这一点?使用互斥锁确实会降低性能(请参阅)。我相信在java中,有一个关键字可以在变量声明中使用来完成(它被称为“同步”),但是C++中是否有这样的事情? 我知道volatile不是我要找的关键词 非常感谢。从描述来看,您可能只需
非常感谢。从描述来看,您可能只需要和相关的减量功能 编辑-这些是Windows函数。。。我没有停下来问哪个平台。大多数处理器都有“递增”和“递减”指令——在很大程度上,它们是如何在机器级别实现互斥的 您可以在自己的代码中访问这些原子指令。Windows提供了该功能,并且。在x86汇编语言中,您可以直接使用
锁CMPXCHG
和kin
C++对这些概念一无所知——你必须自己使用它们;C++中没有线程安全的神奇关键字。
请参见您可以对计数器变量使用原子类型,比如sig_atomic_t(在GNU libc中)。这样就不需要同步,因为竞争条件无法发生,所以对该变量的操作保证是原子操作。在Win32 IntelockedIncrement/IntelockedIncrement64和相关操作中,编译为x86指令,允许对32或64位字执行处理器级原子操作(取决于您的体系结构). 对于一个简单的计数器来说,这很好,但是如果您试图用多个单词同步一个较大的结构,那么它自然不起作用 PS from,您需要在x86上运行的非Win32系统上实现此功能的相应asm
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 );
}
虽然使用原子操作可能是最有效的,但在多个函数中使用原子操作并不妨碍在此代码或任何其他代码中使用关键部分—只需编写一个函数:
void IncDec( bool inc ) {
EnterCritical Section( theCS );
if ( inc ) {
theVar++;
}
else {
thevar--;
}
LeaveCriticalSection( theCS );
}
并从其他函数中计算它
这种情况下的一个关键部分是
不合适,因为有更多
一个以上的函数,可以改变
有问题的变量
这是一个常见的场景,其中使用临界段,您需要确保访问同一个临界段时(访问互斥体或使用哪种保护)时访问变量的每一段代码。正如其他人提到的,
< P>,在当前C++标准中没有支持原子变量访问的任何东西。如果你要C++库支持(虽然我不完全清楚),有一个正在进行的尝试来模仿即将到来的C++标准的原子支持。 在这种情况下,临界截面是不合适的,因为有不止一个函数可以改变所讨论的变量 如果您不使用关键部分来修改单个函数,您如何知道您已经找到了变量可能访问的所有位置此外,您需要声明变量volatile,只需确保编译器不会无意中优化对该变量的任何访问。因此,在变量声明之前没有任何内容可以指定必须以原子方式访问该变量?我知道const、易变和易失的是C++限定词,但它们不符合要求。“安迪不,没有。”当前的C++标准根本不解决线程问题,只要计数器只由单个进程访问,关键部分仍然可以工作。它可以由同一进程中的多个函数使用。事实上,关键部分比Mutexts.re Java快:不,
synchronized
在Java中相当于一个关键部分,它不同于volatile
和原子递增/递减。sig_原子_t
具有原子写入(即,您不需要担心在上下文切换之前更新的变量只有3字节),但不需要原子增量/递减。请参见这个问题:谢谢。C++确实有一些东西可以使线程局部变量(线程),但它可能具体地指向Windows平台。@安迪:使变量线程仿射-这意味着它们不能在线程之间共享(好吧,至少不能违反它们的目的)。@Andy:噢,而且_declspec(线程)不是windows专用的,它是VC++专用的。qt库有一个很好的原子操作实现