我有一些看起来像这样的代码:
主题0:
CMyOtherClass *m_myclass;
CMyClass::SomeFunc(DWORD SomeParam)
{
m_myclass = new CMyOtherClass(SomeParam);
}
主题1:
CMyClass::InsideSecondThread()
{
MySecondThreadFunc(*m_myclass);
}
CMyClass::MySecondThreadFunc(MyOtherClass& myclass)
{
// do something with myclass variable....
// What about thread safety??? Is this not now a shared variable?
// or have we passed a copy and are we safe?
// SomeParam should be the same while in this thread, however it can be changed by Thread 0
}
所以我的问题是,如果你跨越线程传递这个m_myclass变量,这个线程是否安全?
答案 0 :(得分:4)
这不是线程安全的。
答案 1 :(得分:2)
这不是线程安全的。
如果线程1在线程0创建对象之前执行,那么最终会访问线程1中的NULL指针。(假设m_myclass
在构造函数中初始化为NULL)
另一点是:
CMyClass::MySecondThreadFunc(MyOtherClass& myclass)
myclass
对象是共享对象,来自不同线程的任何操作都可能产生问题。
除非有共享的静态成员,否则本地副本应该适用于线程安全。
答案 2 :(得分:0)
这不是线程安全的,因为两个线程都在访问相同的内存。
正如你的代码所代表的那样,只要线程0在线程1启动之前分配内存,那么你应该没有问题,因为线程0除了分配之外什么都不做。如果您更改了线程0代码以便它开始修改类实例,那么您将开始遇到问题。
[编辑] 删除了我认为应该是线程安全的示例。这里有另一篇关于SO的帖子,要求whether changing a pointer is considered an atomic action值得一读。
答案 3 :(得分:0)
您可以创建一个包含两个成员的新CMyOtherThreadSafeClass
CMyOtherClass *m_myclass
和CRITICAL_SECTION cs
。 InitializeCriticalSection
构造函数中的InitializeCriticalSectionAndSpinCount
函数应CMyOtherThreadSafeClass
或更好,并使用EnterCriticalSection
和LeaveCriticalSection
(请参阅http://msdn.microsoft.com/en-us/library/aa910712.aspx和http://msdn.microsoft.com/en-us/library/ms686908.aspx )如果您需要访问CMyOtherClass *m_myclass
成员(阅读或修改,分配或免费),无处不在。
您可以在CMyOtherThreadSafeClass
中添加方法,以便更轻松地使用EnterCriticalSection
和LeaveCriticalSection
。如果程序的所有线程都使用EnterCriticalSection
和LeaveCriticalSection
,那么您的程序将是线程安全的。
答案 4 :(得分:0)
如果仅在创建第二个线程之前调用CMyClass::SomeFunc
,则表示没有竞争条件。
否则,它基本上是防止双重检查锁定工作的相同问题:指针可以在实际构造对象之前分配给m_myclass
,然后线程使用未构造的(或部分构造的)对象