我有一个启动了线程的MFC类,并且线程需要修改主类的CString成员。
我讨厌互斥锁,所以必须有一种更简单的方法来做到这一点。
我正在考虑使用boost.org库或atl :: atomic或shared_ptr变量。
读取和写入字符串的最佳方法是什么?是线程安全的?
class MyClass
{
public:
void MyClass();
static UINT MyThread(LPVOID pArg);
CString m_strInfo;
};
void MyClass::MyClass()
{
AfxBeginThread(MyThread, this);
CString strTmp=m_strInfo; // this may cause crash
}
UINT MyClass::MyThread(LPVOID pArg)
{
MyClass pClass=(MyClass*)pArd;
pClass->m_strInfo=_T("New Value"); // non thread-safe change
}
根据MSDN,shared_ptr会自动https://msdn.microsoft.com/en-us/library/bb982026.aspx
这是一个更好的方法吗?
#include <memory>
class MyClass
{
public:
void MyClass();
static UINT MyThread(LPVOID pArg);
std::shared_ptr<CString> m_strInfo; // ********
};
void MyClass::MyClass()
{
AfxBeginThread(MyThread, this);
CString strTmp=m_strInfo; // this may cause crash
}
UINT MyClass::MyThread(LPVOID pArg)
{
MyClass pClass=(MyClass*)pArd;
shared_ptr<CString> newValue(new CString());
newValue->SetString(_T("New Value"));
pClass->m_strInfo=newValue; // thread-safe change?
}
答案 0 :(得分:1)
你可以实现某种无锁方式来实现它,但这取决于你如何使用MyClass和你的线程。如果您的线程正在处理某些数据并在处理完之后,它需要更新MyClass,然后考虑将您的字符串数据放在其他类中,例如:
struct StringData {
CString m_strInfo;
};
然后在你的MyClass中:
class MyClass
{
public:
void MyClass();
static UINT MyThread(LPVOID pArg);
StringData* m_pstrData;
StringData* m_pstrDataForThreads;
};
现在,这个想法是在你的ie。您使用m_pstrData的主线程代码,但您需要使用atomics来存储指向它的本地指针,即:。
void MyClass::MyClass()
{
AfxBeginThread(MyThread, this);
StringData* m_pstrDataTemp = ATOMIC_READ(m_pstrData);
if ( m_pstrDataTemp )
CString strTmp=m_pstrDataTemp->m_strInfo; // this may NOT cause crash
}
一旦您的线程完成处理数据,并想要更新字符串,您将原子地将m_pstrDataForThreads
分配给m_pstrData
,并分配新的m_pstrDataForThreads
,
问题在于如何安全地删除m_pstrData,我想你可以在这里使用std :: shared_ptr。
最后它看起来有点复杂,IMO并不值得付出努力,至少很难判断这是否真的是线程安全的,而且当代码变得更复杂时 - 它仍然是线程安全的。这也适用于单个工作线程的情况,你说你有多个线程。这就是为什么关键部分是一个起点,如果它太慢,那么考虑使用无锁方法。
顺便说一句。根据字符串数据更新的频率,您还可以考虑使用PostMessage
将指向新字符串的指针安全地传递给主线程。
[编辑]
ATOMIC_MACRO不存在,它只是一个让它编译使用的占位符即。 c ++ 11 atomics,例如:
#include <atomic>
...
std::atomic<uint64_t> sharedValue(0);
sharedValue.store(123, std::memory_order_relaxed); // atomically store
uint64_t ret = sharedValue.load(std::memory_order_relaxed); // atomically read
std::cout << ret;
答案 1 :(得分:1)
我会通过使用void SetStrInfo(const CString& str)
{
[Lock-here]
m_strInfo = str;
[Unlock-here]
}
保护变量来使用更简单的方法:
CCriticalSection
对于锁定和解锁,我们可以使用CSingleLock
(类成员),或将其包裹在std
RAII周围。出于性能原因,我们也可能使用slim-reader writer locks(用RAII包装 - 编写一个简单的类)。我们也可以使用更新的C ++技术进行RAII锁定/解锁。
叫我老派,但对我来说 <tr><td><%out.println(rs.getInt("userID")); %></td></tr>
<tr><td><%out.println(rs.getDate("dob")); %></td></tr>
<tr><td><%out.println(rs.getString("gender")); %></td></tr>
<tr><td><%out.println(rs.getString("firstName")); %></td></tr>
<tr><td><%out.println(rs.getString("lastName")); %></td></tr>
命名空间有一套复杂的选项 - 并不适合所有人,而且每个人都适合。