不,分配不是完全线程安全的。
我编写了一个创建两个线程的测试程序。它们都包含指向包含 cv::Mat 的对象的 shared_ptr。一个线程将该 cv::Mat 分配给一个随机生成的图像,而另一个线程制作该 cv::Mat 的本地副本。
这会立即因双重释放而崩溃。如果写入线程在复制线程开始复制时覆盖了先前的线程,它将复制一个 cv::Mat,其内部数据 ptr 刚刚被删除。当复制线程的本地副本超出范围时,它会尝试再次释放它。
volatile bool g_done = false;
struct Object
{
cv::Mat cvMask;
};
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
void thread1(boost::shared_ptr<Object> sharedObj)
{
while(!g_done)
{
sharedObj->cvMask = cv::Mat::ones(1 + (rand()% 1024), 1+(rand()%768), CV_8UC1);
}
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
void thread2(boost::shared_ptr<Object> sharedObj)
{
while(!g_done)
{
cv::Mat localCopy = sharedObj->cvMask;
}
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
void sigHandler(int signum)
{
fprintf(stderr, "Quitting...\n");
g_done = true;
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
int main(int argc, char** argv)
{
signal(SIGINT, sigHandler);
boost::shared_ptr<Object> sharedObj(new Object);
sharedObj->cvMask = cv::Mat::ones(1024,768, CV_8UC1);
boost::thread* t1 = new boost::thread(boost::bind(&thread1, _1), sharedObj);
boost::thread* t2 = new boost::thread(boost::bind(&thread2, _1), sharedObj);
while(!g_done)
{
usleep(1e6);
}
t1->join();
t2->join();
delete t1;
delete t2;
return 0;
}