单例模式在类只允许一个实例时用到
以下是摘自“Design Patterns Elements of Reusable Object-Oriented Software”一书中单例模式实现:
class Singleton {
public:
static Singleton* Instance();
protected:
Singleton(){};
private:
static Singleton* _instance;
};
Singleton* Singleton::_instance = 0;
Singleton* Singleton::Instance () {
if (_instance == 0) {
_instance = new Singleton();
}
return _instance;
}
在Singleton::Instance ()中,_instance的检测与修改不是原子操作,存在竞态条件
当多个线程同时检测_instance,且此时_instance=0,这些线程都会进入if控制块,new会到堆中去为Singleton分配内存;由于这些线程都为Singleton分配了内存,且只有一个会赋值到_instance,其它的就无法引用而出现内存泄露。
用以下例子来扩大化问题,因内存泄露而造成进程的coredump
/* singletonrace.cpp */
1 #include <iostream>
2 #include <cstdlib>
3 #include <sstream>
4 #include <cerrno>
5 #include <cstring>
6
7 #define MAX 1024
8 #define ARRAYSIZE 1024*1024*50
9
10 class Singleton {
11 public:
12 static Singleton* Instance(int nsecs);
13 protected:
14 Singleton();
15 private:
16 static Singleton* _instance;
17 int array[ARRAYSIZE];
18 };
19
20 Singleton* Singleton::_instance = 0;
21
22 Singleton::Singleton() { }
23 /*
24 Singleton::Singleton() {
25 int idx;
26 for (idx = 0; idx < ARRAYSIZE; idx++) {
27 array[idx] = 0;
28 }
29 }
30 */
31
32 Singleton* Singleton::Instance (int threadId) {
33 if (_instance == 0) {
34 ::sleep(threadId%32 + 3);
35 _instance = new Singleton();
36 }
37 return _instance;
38 }
39
40 int runningThread = 0;
41
42 void * fun(void *id){
43 runningThread++;
44 int threadId = *(int *)id;
45 Singleton::Instance(threadId);
46 runningThread--;
47 }
48
49 int main(int argc, char *argv[])
50 {
51 int idx = 0;
52 pthread_attr_t thrattr;
53 pthre