具有全局变量的C ++多线程

时间:2011-06-23 07:32:41

标签: c++ multithreading

任何人都知道原始全局变量是否是线程安全的?

// global variable
int count = 0;

void thread1()
{
   count++;
}

void thread2()
{
   count--;
   if (count == 0) print("Stuff thing");
}

我是否可以这样做而没有count的任何锁定保护?

谢谢。

6 个答案:

答案 0 :(得分:6)

这不是线程安全的。你这里有种族条件。原因是count++不一定是原子的(意味着不是单个处理器操作)。首先加载该值,然后递增,然后写回。在每个步骤之间,另一个线程也可以修改该值。

答案 1 :(得分:3)

不,不是。它可能可能,取决于实现,编译时选项甚至是月相。

但是标准并没有强制要求某些东西是线程安全的,特别是因为在当前标准中没有任何线程

另请参阅here以获取有关此类问题的更详细分析。

如果您正在使用支持线程的环境,则可以使用互斥锁:例如,检查POSIX线程下的pthread_mutex_*调用。

如果您正在编写C ++ 0x / C ++ 11,请使用互斥锁或该标准中详述的原子操作之一。

答案 2 :(得分:0)

它是一个全局变量,因此多个线程可以竞争改变它。它不是线程安全的。

使用互斥锁。

答案 3 :(得分:0)

总的来说,不,你无法逃避。在你琐碎的例子中,它可能会起作用,但它不可靠。

答案 4 :(得分:0)

只有在PC上有1个带有++和 - 原子操作的CPU时,它才是线程安全的。

如果你想让它的线程安全,这就是Windows的方式:


LONG volatile count = 0;

void Thread1()
{
    ::InterlockedIncrement( &count );
}

void Thread2()
{
    if(::InterlockedDecrement( &count ) == 0 )
    {
       printf("Stuf");
    }
}


答案 5 :(得分:0)

你需要两件事来安全地通过两个或更多线程安全地使用一个对象:操作的原子性和排序保证。

有些人会假装在某些平台上你在这里尝试的是安全的,例如任何类型int的操作代表那些平台是原子的(甚至递增或其他)。这样做的问题是您不一定有订购保证。因此,当希望并知道将同时访问此特定变量时,编译器不会。 (并且编译器正确地假设这个变量一次只能被一个线程使用:你不希望每个变量都被视为可能被共享。性能后果将是非常糟糕的。)

所以不要这样使用原始类型。您无法保证语言,即使某些平台有自己的保证(例如原子性),您也无法告诉编译器该变量是与C ++共享的。要么使用原子类型的编译器扩展,C ++ 0x原子类型,要么使用库解决方案(例如互斥锁)。并且不要让这个名称误导你:为了真正有用,原子类型必须提供排序保证以及名称附带的原子性。