让我们有一个递增全局原子整数的函数,然后我们将该值存储在非原子局部变量中
_Atomic int atom = 0 ;
void function( void )
{
int a = atom++ ;
}
将上述代码与多个线程一起使用时,a
是否始终具有唯一值。如果它会像某些评论者所建议的那样,那么atomic_fetch_add
等函数的重点是什么。
答案 0 :(得分:3)
我不熟悉“_Atomic”关键字。这是新的C ++ 11吗?无论如何,您应该使用内置于大多数平台和cpu体系结构中的原子内在函数。 (ala“锁定添加”在x86中)。
在GCC / Clang上,该函数想要调用__sync_add_and_fetch。在Windows上,它被称为InterlockedIncrement。
在一些仍然以i386为目标的gcc架构中,您必须在程序集中手动执行此操作。 (虽然这不适用于真正的80386,但锁定内在函数直到80486才被引入,但我离题了......)
unsigned int xadd_4(volatile void* pVal, unsigned int inc)
{
unsigned int result;
unsigned int* pValInt = (unsigned int*)pVal;
asm volatile(
"lock; xaddl %%eax, %2;"
:"=a" (result)
: "a" (inc), "m" (*pValInt)
:"memory" );
return (result);
}
int AtomicIncrement(int* pInt)
{
COMPILE_TIME_ASSERT(sizeof(int)==4);
// InterlockedIncrement
unsigned int result = xadd_4(pInt, 1) + 1;
return (int)result;
}
答案 1 :(得分:0)
您可以使用程序集插入,使用CompareAndSwap操作(cas)。 对于intel / gcc,以下示例工作(使用cmpxchg):
static inline uint32_t u32cas(volatile uint32_t *ptr, uint32_t old_val, uint32_t new_val) {
uint32_t prev_val;
__asm__ __volatile__("lock; cmpxchgl %k1,%2"
: "=a"(prev_val)
: "q"(new_val), "m"(*(volatile uint32_t *)(ptr)), "0"(old_val)
: "memory");
return prev_val;
}
uint32_t atom = 0;
void atomic_increment() {
uint32_t x;
do {
x = atom;
} while(u32cas(&atom, x, x + 1) != x);
}
另外,在FreeBSD上,您可以使用
man atomic
答案 2 :(得分:-3)
x++
或++x
只是x=x+1
;
你必须使用一些互斥锁。