C++ 数据竞赛?但是问题出在哪里呢?
下面的简单程序偶尔会崩溃,但我不明白它会有什么问题 它是用“-pthread-std=c++11-g-O2-pie-fpie-std=c++11”编译的 valgrind drd报告了一场数据竞赛,但我不明白为什么C++ 数据竞赛?但是问题出在哪里呢?,c++,multithreading,crash,C++,Multithreading,Crash,下面的简单程序偶尔会崩溃,但我不明白它会有什么问题 它是用“-pthread-std=c++11-g-O2-pie-fpie-std=c++11”编译的 valgrind drd报告了一场数据竞赛,但我不明白为什么 #include <pthread.h> #include <stdlib.h> #include <unistd.h> #include <iostream> bool running; pthread_rwlock_t _rwlo
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
bool running;
pthread_rwlock_t _rwlock;
class Dummy {
public:
Dummy() : _refs(0) {
Ref();
}
volatile int _refs;
void Ref() {
++_refs;
}
void Unref() {
--_refs;
if (_refs <= 0) {
delete this;
}
}
};
static Dummy* s_dummy;
Dummy* get_dummy() {
pthread_rwlock_rdlock(&_rwlock);
Dummy* ret = s_dummy;
ret->Ref();
pthread_rwlock_unlock(&_rwlock);
return ret;
}
void *work1(void*) {
while (running) {
Dummy* new_dummy = new Dummy();
pthread_rwlock_wrlock(&_rwlock);
Dummy* to_del = s_dummy;
s_dummy = new_dummy;
pthread_rwlock_unlock(&_rwlock);
to_del->Unref();
}
}
void *work2(void*) {
while (running) {
Dummy* p = get_dummy();
p->Unref();
}
}
int main() {
running = true;
pthread_rwlock_init(&_rwlock, NULL);
s_dummy = new Dummy();
pthread_t threads[2];
threads[0] = pthread_create(&threads[0], NULL, work1, NULL);
threads[0] = pthread_create(&threads[1], NULL, work2, NULL);
sleep(30);
running = false;
void* ret;
for (int i = 0; i < 2; ++i) {
pthread_join(threads[i], &ret);
}
return 0;
}
#包括
#包括
#包括
#包括
布尔跑;
pthread_rwlock_t_rwlock;
类虚拟{
公众:
Dummy():\参考文献(0){
Ref();
}
挥发性内标;
void Ref(){
++_参考文献;
}
void Unref(){
--_参考文献;
如果(_refsref();
pthread_rwlock_unlock(&_rwlock);
返回ret;
}
无效*工作1(无效*){
(跑步时){
虚拟*新虚拟=新虚拟();
pthread_rwlock_rwlock(&_rwlock);
假人*至_del=s_假人;
s_假人=新的_假人;
pthread_rwlock_unlock(&_rwlock);
到_del->Unref();
}
}
无效*工作2(无效*){
(跑步时){
Dummy*p=get_Dummy();
p->Unref();
}
}
int main(){
运行=真;
pthread_rwlock_init(&_rwlock,NULL);
s_假人=新假人();
pthread_t线程[2];
线程[0]=pthread_create(&threads[0],NULL,work1,NULL);
线程[0]=pthread_create(&threads[1],NULL,work2,NULL);
睡眠(30);
运行=错误;
void*ret;
对于(int i=0;i<2;++i){
pthread_join(线程[i]、&ret);
}
返回0;
}
work1和work2中的两个UNREF可能会冲突。没有任何东西可以阻止删除同时发生在两个线程中
另外,您应该使运行易失性,或者更好的是原子性
最后,对于一些可以使用共享的ptr轻松解决的问题,似乎需要做大量的工作。下面的代码与您的代码相当:
#include <atomic>
#include <memory>
#include <thread>
class Dummy {
};
std::atomic<bool> running = true;
static std::shared_ptr<Dummy> s_dummy = std::make_shared<Dummy> ();
void work1 () {
while (running)
s_dummy = std::make_shared<Dummy> ();
}
void work2 () {
while (running)
s_dummy = nullptr;
}
int main() {
std::thread t1 (work1);
std::thread t2 (work2);
sleep (30);
running = false;
t1.join ();
t2.join ();
return 0;
}
#包括
#包括
#包括
类虚拟{
};
std::原子运行=真;
静态std::shared_ptr s_dummy=std::make_shared();
无效工作1(){
(跑步时)
s_dummy=std::使_共享();
}
无效工作2(){
(跑步时)
s_dummy=nullptr;
}
int main(){
标准:螺纹t1(工作1);
标准:螺纹t2(工作2);
睡眠(30);
运行=错误;
t1.join();
t2.join();
返回0;
}
由于您没有添加消息,因此我无法说明您收到的确切消息,但是您至少在\u refs
上有一个数据竞争,这可能会导致双重删除
例如,两个线程可以同时位于同一对象上的Unref
,且_refsinitial==2
假设两个线程都运行-\u refs
,那么\u refs
的值将为0。然后两个线程都检查refs
是否为零,并且由于\u refs
是易失性的,因此它们都从内存中读取值0,并且都删除
您可能希望\u refs
是一个原子变量,而不是一个易失性。不应该线程[0]=pthread\u create(&threads[1],NULL,work2,NULL);
bethreads[1]=pthread\u create(&threads[1],NULL,work2,NULL);
实际上是对线程[0]的两个赋值
应该被删除,您只需调用pthread\u create()
如果您不想检查错误,因为赋值将破坏该函数编写的线程标识符。我想可能是\u refs
上的数据竞争?您可以添加给出的消息吗?您是否在x86以外的处理器上运行此操作?比如说,ARM?如果是这样,我怀疑不同内核上的缓存不正确rly已同步。我是说_refs导致了故障、数据竞争,但这怎么可能发生呢?