偶尔发生以下简单的程序崩溃,但我不明白它可能有什么问题?
用' -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 _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;
}
答案 0 :(得分:1)
由于您没有添加,因此我无法说出您收到的确切消息,但是您至少在_refs
上进行了数据竞争,并且可能会导致双delete
。
例如,两个线程可以同时位于同一个对象的Unref
内,_refs最初== 2.
假设两个线程都运行--_refs
,_refs
的值将为0.然后两个线程检查refs
是否为零,并且_refs
是不稳定的两者都从内存中读取值0并且都删除。
_refs
你可能想要的是 atomic 变量,而不是volatile。
答案 1 :(得分:0)
work1和work2中的两个unrefs可能会发生冲突。没有什么能阻止同时在两个线程中发生删除。
此外,你应该使running
变得不稳定,或者更好。
最后,对于可以使用shared_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;
}