BOOST Thread Full Introduction

Source: Internet
Author: User

1 Creating Threads

First look at Boost::thread's constructor, Boost::thread has two constructors:
(1) thread (): Constructs a thread object that represents the current thread of execution;
(2) explicit thread (const boost::function0& THREADFUNC):
Boost::function0 can be viewed simply as: a function with no return (return void), no arguments. The function here can also be a function of the class overload operator (), which passes in a function object instead of a function pointer, so that a class with a general function attribute can also be passed in as a parameter, in the following example.

The first way: the simplest way

void Hello () {         <<         "Hello World, I ' m a thread! "         << Std::endl;}    int Main (intChar* argv[]) {         boost::thread thrd (&hello);         Thrd.join ();          return 0 ; }

The second way: a complex type object is used as a parameter to create a thread:

Boost::mutex Io_mutex;structCount {count (intID ): ID (ID) {}void operator()()         {                  for(inti =0; I <Ten; ++i) {boost::mutex::scoped_lockLock(Io_mutex); Std::cout<< ID <<": "<< I <<Std::endl; }         }                 intID;}; intMainintargcChar*argv[]) {Boost::thread Thrd1 (count (1)); Boost::thread Thrd2 (COUNT (2));         Thrd1.join ();         Thrd2.join (); return 0; }

The third way: Create threads inside the class;

classhelloworld{ Public: Static voidHello () {std::cout<<"Hello World, I ' m a thread!"<<Std::endl;} Static voidstart () {Boost::thread thrd (hello); Thrd.join (); } }; intMainintargcChar*argv[])  {Helloworld::start (); return 0;} Both the start () and the Hello () methods must be static methods. 

(2) if the start () and Hello () methods are required to be static methods, the following method is used to create the thread:

classhelloworld{ Public: voidHello () {std::cout<<"Hello World, I ' m a thread!"<<Std::endl;} voidstart () {Boost::function0<void> f = Boost::bind (&helloworld::hello, This);  Boost::thread thrd (f); Thrd.join (); } }; intMainintargcChar*argv[]) {HelloWorld Hello; Hello.start ();return 0;}

The fourth method: Create a thread outside of the class with the class intrinsic function;

classhelloworld{ Public: voidHelloConstSTD::string&str) {Std::cout< }}; intMainintargcChar*argv[]) {HelloWorld obj; Boost::thread thrd (Boost::bind (&helloworld::hello,&obj,"HelloWorld, I"'M a thread!" ) ) ;Thrd.join ();return 0;}

If a thread needs to bind a function with parameters, it needs to use Boost::bind. For example, to use Boost::thread to create a thread to execute a function: void f (int i), if this is the case: Boost::thread thrd (f) is wrong, because the thread constructor declaration accepts a type that has no parameters and returns a type of void , and does not provide the value of the parameter I f also cannot run, then can write: Boost::thread thrd (Boost::bind (f,1)). The binding problem involving the parameter function is basically boost::thread, boost::function, and Boost::bind are used together.

2 Mutex

  Anyone who writes too many thread routines knows the importance of avoiding simultaneous access to shared areas by different threads. If a thread changes one of the data in the shared area while the other is reading the data, the result will be undefined. In order to avoid this situation, some special primitive types and operations will be used. The most basic of these is the mutex (mutex,mutual exclusion abbreviation). A mutex allows only one thread at a time to access the shared area. When a thread wants to access a shared area, the first thing to do is lock the mutex. If the other thread has locked the mutex, you must wait for that thread to unlock the mutex so that only one thread can access the shared area at the same time.

There are many variants of the concept of mutexes. The Boost line libraries supports two major types of mutexes, including simple mutexes and recursive mutexes (recursive mutexes). If the same thread locks on the mutex two times, a deadlock (deadlock) occurs, which means that all threads waiting to be unlocked will wait. With a recursive mutex, a single thread can lock the mutex multiple times and, of course, must unlock the same number of times to ensure that other threads can lock the mutex.

In these two categories of mutexes, there are multiple variants of how threads are locked. There are three ways a thread can lock a mutex:

    1. Wait until no other thread locks the mutex.
    2. Returns immediately if another mutex has been locked for the mutex.
    3. Wait until no other thread mutex locks until it expires.

It seems that the best mutex type is a recursive mutex, which can use all three lock forms. Every variant, however, has a price. So boost line libraries allows you to use the most efficient mutex types depending on your needs. The Boost line libraries provides 6 of the mutex types, which are sorted by efficiency:

Boost::mutex,

Boost::try_mutex,

Boost::timed_mutex,

Boost::recursive_mutex,

Boost::recursive_try_mutex,

Boost::recursive_timed_mutex

If the mutex is unlocked, a deadlock will occur. This is a common mistake, and the Boost line libraries is to make it impossible (at least it is difficult). Locking and unlocking the mutex directly is not possible for users of the Boost line libraries. The mutex class implements the locking and unlocking of the mutex by teypdef the type defined in the RAII. This is what you know about the scope lock mode. To construct these types, you pass in a reference to a mutex. The constructor locks the mutex, and the destructor unlocks the mutex. C + + guarantees that the destructor will be called, so even if there is an exception thrown, the mutex will always be properly unlocked.

3. Condition Variables

 Sometimes it is not enough to just lock in shared resources to use it. Sometimes shared resources can be used only when they are in certain States. For example, if a thread is to read data from the stack, it must wait for the data to be stacked if there is no data in the stack. It is not enough to use a mutex in this case for synchronization. Another way of synchronizing--The condition variable, can be used in this case.

The use of condition variables is always associated with mutexes and shared resources. The thread first locks the mutex and then verifies that the state of the shared resource is in a available state. If not, then the thread waits for the condition variable. To point to such an operation, the mutex must be unlocked at the time of the wait so that other threads can access the shared resource and change its state. It also has to be guaranteed that the mutex is locked from waiting for the thread to return. When another thread changes the state of a shared resource, it notifies the thread that is waiting for the condition variable and returns it to the waiting thread.

List4 is a simple example of using boost::condition. There is a class that implements bounded buffers and a fixed-size first-in-one container. This buffer is thread-safe due to the use of the mutex Boost::mutex. Put and get use condition variables to ensure that the thread waits for the required state to complete the operation. There are two threads created, one putting 100 integers in buffer and the other pulling them out of buffer. This bounded cache can only hold 10 integers at a time, so these two threads must periodically wait for another thread. To verify this, put and get output diagnostic statements in Std::cout. Finally, when two threads are finished, the main function is executed.

4. Thread-Local Storage

  Most of the functions are not reentrant. This means that when a function is called by a thread, it is unsafe if you call the same function again. A non-reentrant function saves a static variable by successive calls or returns a pointer to the static data. For example, Std::strtok is not reentrant because it uses static variables to hold strings that are to be split into symbols.

There are two ways to make non-reusable functions a reusable function. The first method is to change the interface, using pointers or references instead of where static data was originally used. For example, POSIX defines a reentrant variable in Strok_r,std::strtok, which replaces static data with an additional char** parameter. This approach is simple and provides the best possible results. But this has to change the public interface, which means you have to change the code. Instead of changing the public interface, the other method uses the local storage thread (thread local storage) instead of the static data (sometimes it becomes a special thread store, thread-specific storage).

Boost Line libraries provides a smart pointer boost::thread_specific_ptr to access local storage threads. When each thread first uses an instance of this smart pointer, its initial value is NULL, so it must first check if it is empty and assign a value to it. Boost line libraries guarantees that the data saved in the local storage thread will be purged after it is finished.

LIST5 is a simple example of using BOOST::THREAD_SPECIFIC_PTR. Two threads were created to initialize the local storage thread, and there were 10 loops, each increasing the value pointed to by the smart pointer and outputting it to std::cout (because Std::cout is a shared resource, it is synchronized through the mutex). The main thread waits for the two threads to exit after the end of the thread. From this example output you can see that each thread handles its own data instances, although they all use the same boost::thread_specific_ptr.

BOOST Thread Full Introduction

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.