一、简介
线程安全是一个比较严肃的问题,如果处理不好,可能导致数据被破坏,程序崩溃等问题,如何来处理多线程的并发问题?在windows平台有相应的api给你用于控制并发,如互斥锁,信号量,事件,临界区等,定要熟练掌握,当然现在STL库已强大到兼容不同的硬件系统了,当然对于winApi同步可以看这里:
互斥锁,信号量,事件,临界区详情
二、分析安全原理
基于conditon_variable类实现线程安全,先来看看它有什么API使
wait阻塞自己,等待唤醒
wait_for阻塞自己,等待唤醒,最多等待一段时间
wait_until阻塞自己,等待唤醒,最多等待到某个时间点
notify_one 唤醒一个等待在这个条件变量上的线程
notify_all 唤醒所有等待在这个条件变量上的线程
三、队列代码
template<typename T> class ThreadSafe_Queue
{
private:
mutable mutex m_mut;
queue<T> m_queue;
condition_variable m_data_cond;
public:
ThreadSafe_Queue() {}
ThreadSafe_Queue(const ThreadSafe_Queue&) = delete;
void push(T data)
{
lock_guard<mutex> lg(m_mut);
m_queue.push(data);
m_data_cond.notify_one();
}
void WaitPop(T&t)
{
unique_lock<mutex> ul(m_mut);
m_data_cond.wait(ul, [this] {return !m_queue.empty(); });
t = m_queue.front();
m_queue.pop();
}
shared_ptr<T> WaitPop()
{
unique_lock<mutex> ul(m_mut);
m_data_cond.wait(ul, [this] {return !m_queue.empty(); });
shared_ptr<T> res(make_shared<T>(m_queue.front()));
m_queue.pop();
return res;
}
bool TryPop(T &t)
{
lock_guard<mutex> lg(m_mut);
if (m_queue.empty())
return false;
t = m_queue.front();
m_queue.pop();
return true;
}
shared_ptr<T> TryPop()
{
lock_guard<mutex> lg(m_mut);
if (m_queue.empty())
return shared_ptr<T>();
shared_ptr<T> res(make_shared<T>(m_queue.front()));
m_queue.pop();
return res;
}
bool IsEmpty()
{
lock_guard<mutex> lg(m_mut);
return m_queue.empty();
}
};
四、一个小例子
开了两个线程,用于测试线程队列是否安全,thread_Fuc2用于插入数据,thread_Fuc用于出队操作,经过测试,达到了安全。
ThreadSafe_Queue<int> g_queue;
int g_index = 10;
void thread_Fuc()
{
cout << "thread_fuc1 start\n";
while (true)
{
int value=0;
g_queue.WaitPop(value);
printf("wait_and_pop done! value=%d thread id:%d\n",value,GetCurrentThreadId());
}
}
void thread_Fuc2()
{
cout << "thread_fuc2 start\n";
while (true)
{
Sleep(1000);
g_index++;
g_queue.push(g_index);
}
}
int main()
{
thread thd(thread_Fuc);
thd.detach();
thread thd2(thread_Fuc2);
thd2.detach();
int a;
while (cin >> a){;}
return 0;
}
结果:
---------------------
原文:https://blog.csdn.net/what951006/article/details/77916490