2016-01-24 43 views
0

我最近开始学习POSIX线程,并且我知道当你有两个线程Main和B时,如果在线程B的创建中引用变量作为void指针,线程B可以连续地在线程Main中更改一个变量。在运行时更改线程的void指针会发生什么?

这使我想知道如何让线程在线程B中不断更改变量。我编写了一个程序来测试是否更改发送的参数通过运行线程B更改线程B,然后更改引用的变量。它没有做任何事情。这个结果是正确的吗?

所以基本上:

void *someFunc(void *var) { 
    int *num=(int*) var; 
    int num2=*num; 
    while (true) { 
     if (num2==1) { 
      *num=3; 
     } else { 
      *num=5; 
     } 
    } 
    return NULL;  
} 

someVar=1; 
pthread_t threadB; 
if(pthread_create(&threadB, NULL, someFunc , &someVar)) { 
    return 1; 
} 
someVar=2; 
//then join both threads later and print someVar 
//will someVar be 3 or 5? 

基本上,当我参考使用线程创建的空指针的变量,将未来该变量的变化会影响新创建的线程?如果不是这样,为了不断改变它,是否有一些特别要求呢?我应该看看锁/互斥锁还是仅将someFunc放入类中并更改其初始化变量? 谢谢!

+1

它被称为[Race Condition](http://stackoverflow.com/questions/34510/what-is-a-race-condition),它触发[undefined behavior](https://en.wikipedia.org/wiki/Undefined_behavior)(即不可能说出会发生什么)。另请注意,自从C++ 11 [在C++中有多线程的标准工具](http://en.cppreference.com/w/cpp/thread),并且不再需要pthread。 – Drop

+1

为了更好地理解[顺序一致](https://en.wikipedia.org/wiki/Sequential_consistency)C++ 11的Data Race Free Memory模型,请参阅着名的Herb Sutter的讲话:[C++ and Beyond 2012:Herb Sutter - 原子<>武器](https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2) – Drop

+0

我意识到我应该看看这类东西的全局变量。谢谢! – msun

回答

-3

因为您通过someFunc指针传递someVar,然后将其复制到指针num,所以对someVar的任何更改都会立即更改* num的值。

但是num2不会受到对someVar的更改的影响,因为num2是分配给线程B堆栈的不同变量。因此,while循环的结果将由分配给num2的值决定,线程开始。这可以是1或2,具体取决于主线程和线程B运行的速度。这种依赖是一种称为“竞争条件”的非确定性行为,您需要非常小心以避免它。

+1

建议使用非同步变量来替代“低级构造”,如“锁和互斥体”,这简直是无稽之谈。当一个线程中的写入操作在另一个线程中变得可见时,您无法保证!请参阅@Drop在评论中提供的链接。 –

+0

也许我应该在这里添加一些缺失的解释:我使用许多不同的机制亲自在C++中完成了大量的多线程。与多线程相关的主要问题是正确性(线程安全性,没有死锁,没有竞争条件)和性能。我的方法是只在真正需要的地方使用锁定。有技术可以在不锁定的情况下进行安全的多线程(请参阅https://en.wikipedia.org/wiki/Multiversion_concurrency_control)。特别是,如果你想要的只是表示一个动作的完成,一个简单的共享指针是最简单和安全的。 –

+0

因此,你在某处存储了该动作的结果,然后设置了标志(我认为这是你的意思是共享指针,而不是'std :: shared_ptr')它完成了吗?写重新排序会打破这一点,所以我不同意这是安全的。使用原子可以使这个工作甚至没有锁定,是真的,但它也不是没有同步。 –

1

线

int num2=*num; 

创建拷贝数的由主线程指向。你有一场比赛,因此:如果在复制之前改变了,有一件事会发生;否则,子线程将永远不会看到更改。

相关问题