C++ 用于生成唯一Id的函数局部静态变量
可能重复:C++ 用于生成唯一Id的函数局部静态变量,c++,c,thread-safety,C++,C,Thread Safety,可能重复: 下面的函数是否每次调用时都返回一个唯一的数字?在多线程场景中呢 int returnUniqueNumber() { static int i = 0; ++i; return i; } 这取决于您的平台,因为您将遇到多线程问题。在windows上,您最好执行以下操作: int returnUniqueNumber() { volatile static long l = 0; return (int)InterlockedIncrement( &l
下面的函数是否每次调用时都返回一个唯一的数字?在多线程场景中呢
int returnUniqueNumber()
{
static int i = 0;
++i;
return i;
}
这取决于您的平台,因为您将遇到多线程问题。在windows上,您最好执行以下操作:
int returnUniqueNumber()
{
volatile static long l = 0;
return (int)InterlockedIncrement( &l );
}
这些函数保证是原子的。以下是Goz关于windows的回答,对于Linux/GCC,请参见此问题/回答:
在这种情况下,您需要
\uuu sync\u add\u and_fetch()
如果您的应用程序是单线程的,那么您发布的代码实际上是生成唯一数字的正确的、符合标准的C/C++方法。但是,由于您正在寻找线程安全解决方案,因此必须深入研究特定于平台的解决方案。Goz有一个很好的Windows解决方案。Mac OS X或iOS上的一个等价物是:
int returnUniqueNumber_APPLE(void) {
static volatile int32_t i = 0;
return (int)OSAtomicIncrement32Barrier(&i);
}
在使用最新的ish GCC编译的任何系统上,都有GCC的内部函数:
int returnUniqueNumber_GCC(void) {
static volatile int i = 0;
return __sync_add_and_fetch(&i, 1);
}
您不应该将
静态int*
强制转换为易失性long*
——相反,在这两种情况下,它都应该是(适当限定的)long*
,并在返回时(或仅由函数隐式地)强制转换为int
。long
和int
(以及Windows'long
typedef)它们的大小并不总是一样的,虽然这种石膏在窗户上可能很好,但它会助长坏习惯。:)@乔纳森:明白了,修正了。我向你致敬,先生+1代表您,1代表简单准确的代码!在int的最大值达到之后,然后是-ve值,它不是旋转回0,1,2@是的。它将计数到2^31-1,然后它将交换到-2^31并计数到0。循环无限延续。这是twos补码编码的主要优点…看起来我们已经介绍了Windows、Linux和MacOS:)不仅仅是Linux,还有大多数*NIXes.)事实上,我们几乎涵盖了所有主要的现代系统。Android可能是剩下的唯一一个,在那里,您可以在函数的返回类型之前抛出一个synchronized
关键字,然后就可以完成了。(Java有正确的原子操作吗?我不是说AtomicInteger
等等)