标签:blog http 使用 os io 数据 for 2014
#include <iostream>
#include <thread>
#include <mutex>
#include <string>
#include <vector>
std::mutex myMutex;
class Stack
{
public:
Stack() {};
~Stack() {};
void pop();
int top() { return data.back(); }
void push(int);
void print();
int getSize() { return data.size(); }
private:
std::vector<int> data;
};
void Stack::pop()
{
std::lock_guard<std::mutex> guard(myMutex);
data.erase(data.end()-1);
}
void Stack::push(int n)
{
std::lock_guard<std::mutex> guard(myMutex);
data.push_back(n);
}
void Stack::print()
{
std::cout << "initial Stack : " ;
for(int item : data)
std::cout << item << " ";
std::cout << std::endl;
}
void process(int val, std::string s)
{
std::lock_guard<std::mutex> guard(myMutex);
std::cout << s << " : " << val << std::endl;
}
void thread_function(Stack& st, std::string s)
{
int val = st.top();
st.pop();
process(val, s);
}
int main()
{
Stack st;
for (int i = 0; i < 10; i++)
st.push(i);
st.print();
while(true) {
if(st.getSize() > 0) {
std::thread t1(&thread_function, std::ref(st), std::string("thread1"));
t1.join();
}
else
break;
if(st.getSize() > 0) {
std::thread t2(&thread_function, std::ref(st), std::string("thread2"));
t2.join();
}
else
break;
}
return 0;
} 运行后的结果之一: 看上去这段代码是线程安全的。事实上并非如此。仍然有资源竞争存在,取决于执行的顺序。如下所示:
元素"6"可能被执行两次,且元素"5"被跳过了。
尽管从上面的运行结果看是正确的,但是代码中仍然存在可能触发资源竞争的条件。换言之,这段代码不是线程安全的。
一种解决方法是将函数top()与pop()合并到一个mutex下面:
int stack::pop()
{
lock_guard<mutex> guard(myMutex);
int val = data.back();
data.erase(data.end()-1);
return val;
}
void thread_function(stack& st, string s)
{
int val = st.pop();
process(val, s);
}
#include <mutex>
#include <deque>
using namespace std;
template< typename T, typename Container = std::deque<T> >
class stack
{
public:
explicit stack(const Container&);
explicit stack(Container&& = Container());
template <typename Alloc> explicit stack(const Alloc&);
template <typename Alloc> stack(const Container&, const Alloc&);
template <typename Alloc> stack(Container&&, const Alloc&);
template <typename Alloc> stack(stack&&, const Alloc&);
// not reliable
bool empty() const;
// not reliable
size_t size() const;
T& top();
T const& top() const;
void push(T const&);
void push(T&&);
void pop();
void swap(stack&&);
}; 此段代码的问题在与empty()与size()是不可靠的。在某个线程调用empty或size之前,其它线程可能已经调用了push或pop对栈进行了改变。stack<int> s;
if(!s.empty())
{
int const value=s.top();
s.pop();
do_task(value);
} 不过,当stack instance共享时,对于一个空栈,调用top()可能导致未知的结果。调用顺序empty() -- > top() -- >pop()不再线程安全。empty()与top()之间,可能有另一个线程调用过了pop().C++11线程指南(七)--资源竞争条件,布布扣,bubuko.com
标签:blog http 使用 os io 数据 for 2014
原文地址:http://blog.csdn.net/shltsh/article/details/38455865