[c++11 concurrent programming] the Mutex race condition

Source: Internet
Author: User
Tags mutex

The basic use of mutexes is described in the previous section, and using mutexes to protect shared data does not solve the problem with race condition if we have a stack data structure similar to Std::stack it provides 5 basic operations push (), pop (), top (), Empty (), and size (). The top () operation here Returns a copy of the top element of the stack, so that we can use a mutex to protect the data inside the stack. However, in the case of race codition, although the use of mutexes protects shared data within each of the stack's interfaces, there are still problems.

#include <deque>template<typename t,typename container=std::d eque<t> >class stack{public:    Explicit stack (const container&);    Explicit Stack (container&& = Container ());    Template <class alloc> Explicit stack (const alloc&);    Template <class alloc> stack (const container&, const alloc&);    Template <class alloc> stack (container&&, const alloc&);    Template <class alloc> stack (stack&&, const alloc&);    BOOL empty () const;    size_t size () const;    t& top ();    T const& Top () const;    void push (T const&);    void push (t&&);    void Pop ();    void swap (stack&&);}; int main () {}

The problem here is that the return value of empty () and size () is unreliable, although the return value is correct when we call both functions, but once returned, other threads can access the stack and push () new data into the stack, based on empty () and size ( The previous return value can cause problems. For example, thread A and thread B get a copy of the same stack top data, thread a performs pop () pops it up, thread B executes, and the second data at the top of the stack pops up directly. This results in the data not being processed.


Therefore, we need to refactor the interface. The scheme used here is to provide two pop () interfaces, a reference to accept the data, and the stack top data to be assigned to the reference parameter within the POP (). Another implementation is to return a pointer to the top data of the stack. The first interface is feasible in most cases, but the disadvantage is that the user needs to construct an instance of the data object first, and also require that the object be assignable. The second interface does not need to return data as a value, but users should pay attention to the use of pointers to avoid memory leaks and other issues.

The reconstructed stack header file is as follows:

#include <exception> #include <memory>struct empty_stack:std::exception{    const char* What () const throw ();}; Template<typename t>class threadsafe_stack{public:    threadsafe_stack ();    Threadsafe_stack (const threadsafe_stack&);    threadsafe_stack& operator= (const threadsafe_stack&) = delete;    void push (T new_value);    Std::shared_ptr<t> pop ();    void Pop (t& value);    BOOL empty () const;}; int main () {}
Because stack does not support assignment operations, it is defined as delete.

The implementation of the stack is as follows:

#include <exception> #include <stack> #include <mutex> #include <memory>struct empty_stack:std    :: exception{const char* What () const throw () {return "empty stack";    }};template<typename t>class threadsafe_stack{private:std::stack<t> data; mutable Std::mutex M;public:threadsafe_stack () {} threadsafe_stack (const threadsafe_stack& Other) {St        d::lock_guard<std::mutex> Lock (OTHER.M);    Data=other.data;    } threadsafe_stack& operator= (const threadsafe_stack&) = delete;        void push (T new_value) {std::lock_guard<std::mutex> lock (m);    Data.push (New_value);        } std::shared_ptr<t> Pop () {std::lock_guard<std::mutex> lock (m);        if (Data.empty ()) throw Empty_stack ();        std::shared_ptr<t> Const RES (std::make_shared<t> (Data.top ()));        Data.pop ();    return res; } void Pop (t& value) {STD::LOCK_GUARD&LT;std::mutex> Lock (m);        if (Data.empty ()) throw Empty_stack ();        Value=data.top ();    Data.pop ();        } bool Empty () const {std::lock_guard<std::mutex> lock (m);    return Data.empty ();    }};int Main () {threadsafe_stack<int> si;    Si.push (5);    Si.pop ();        if (!si.empty ()) {int x;    Si.pop (x); }    }
The stack can be copied, and in the copy constructor, the mutex is used to protect the internal data. To ensure that the internal data is protected by a mutex, you cannot initialize the stack's member variables by using the initialization parameter list.

The use of mutexes to pay attention to the granularity of the problem, the granularity of protection is too small, will miss out some scenes cause race condition. Too large a protection granularity can reduce the execution efficiency of concurrent threads. To achieve the appropriate granularity, multiple mutexes may be required, and the use of multiple mutexes can lead to deadlock problems. In the next section, we'll look at what the deadlock is all about and how to solve the deadlock problem.




Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

[c++11 concurrent programming] the Mutex race condition

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.