最近发现一个问题:
多进程模型中,调用单例对象,发现单例对象在不同进程中打印出来的对象首地址和其成员变量地址是一样的,一开始百思不得其解,还以为单例对象在不同进程中也是共享的呢,但是明显单例对象在不同进程中变量值是独立的。
上代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <vector>
#include <errno.h>
#include <arpa/inet.h>
using namespace std;
class Monitor {
public:
Monitor() : str_("") {
cout << "Monitor()" << endl;
};
virtual ~Monitor() {};
/**
* @brief 实例化
*
*/
static Monitor *getInstance() {
static Monitor *m = NULL;
if (m == NULL) {
m = new Monitor;
}
return m;
}
std::string str_;
};
void child_process() {
sleep(1);
printf("child begin:str=%s, Monitor:%p, Monitor->str_:%p\n", Monitor::getInstance()->str_.c_str(), Monitor::getInstance(), &Monitor::getInstance()->str_);
Monitor::getInstance()->str_ = "I am child";
printf("child end:str=%s, Monitor:%p, Monitor->str_:%p\n", Monitor::getInstance()->str_.c_str(), Monitor::getInstance(), &Monitor::getInstance()->str_);
}
int main(int argc, char **argv){
if (0 == fork()) {
child_process();
} else {
static int num = 0;
printf("father begin:str=%s, Monitor:%p, Monitor->str_:%p\n", Monitor::getInstance()->str_.c_str(), Monitor::getInstance(), &Monitor::getInstance()->str_);
Monitor::getInstance()->str_ = "I am father";
sleep(2);
printf("father end:str=%s, Monitor:%p, Monitor->str_:%p\n", Monitor::getInstance()->str_.c_str(), Monitor::getInstance(), &Monitor::getInstance()->str_);
}
return 0;
}
执行结果:
Monitor()
father begin:str=, Monitor:0x1149010, Monitor->str_:0x1149018
Monitor()
child begin:str=, Monitor:0x1149010, Monitor->str_:0x1149018
child end:str=I am child, Monitor:0x1149010, Monitor->str_:0x1149018
father end:str=I am father, Monitor:0x1149010, Monitor->str_:0x1149018
最后考虑应该是单例对象在父子进程中的虚拟地址是一样的,打印出来的地址一致,但是父子进程内存是独立的,所以单例对象在父进程和子进程中调用,访问的物理内存是不同的。
我们在Monitor构造函数中打印了debug信息,发现父子进程分别调用了构造函数,说明父子进行对单例对象Monitor并不是共享的,事实上也绝不可能是共享的,进程是分配资源的最小单位。
以上记录,为自己思考,并没有求得绝对正确的解释。