C++11多线程编程 第六章: 多线程之间的事件处理

C++11 Multithreading – Part 6: Need of Event Handling

Varun June 1, 2015 C++11 Multithreading – Part 6: Need of Event Handling2018-08-18T15:20:06+00:00C++ 11c++11 ThreadsMultithreading 1 Comment

In this article we will discuss the need of Event Handling in Multi-threading.

Sometimes a thread needs to wait for an event to happen like a condition to become true or a task to be completed by another thread.

For example,

Suppose we are building a network based application. This application does following tasks,

  1. Perform some handshaking with server
  2. Load Data from XML files.
  3. Do processing on data loaded from XML.

As we can see that Task 1 is not dependent on any other Tasks but Task 3 is dependent on Task 2. So, it means Task 1 and Task 2 can be run in parallel by different Threads to improve the performance of application.

So, let’s break this into a multi-threaded application,

Now, it includes two threads,

Responsibilities of Thread 1 are,

  • Perform some handshaking with server.
  • Wait for data to be loaded from XML by Thread 2
  • Do processing on data loaded from XML.

Responsibilities of Thread 2 are,

  • Load data from XML
  • Notify another Thread i.e. waiting for the message.

Multithreaded Application

In above, Thread 1 performs some operations and then waits for an event/condition to happen. The event or condition here is,

Is Data loaded successfully.

Once Thread 1 receives that Event then it performs some processing on the data.

Thread 2, loads the data in parallel when Thread 1 was busy in doing Hand Shake Mechanism.

When Thread 2 successfully loads the data from XML, it then notifies the Thread 1 by signaling that Event.

Now When Event or Condition is signaled then Thread 1 will continue the processing of Data.

What’s the benefit of making it multi-threaded?

When Thread 1 is busy in some handshaking mechanism then Thread 2 will load the data parallel from XML. So, it will increase the performance of application.

Now, how to achieve this,

Option 1:

Make a Boolean global variable with default value false. Set its value to true in Thread 2 and Thread 1 will keep on checking its value in loop and as soon as it becomes true Thread 1 will continue with processing of data. But as it’s a global variable shared by both of the Threads it needs synchronization with mutex. Let’s see its code,

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

#include<iostream>

#include<thread>

#include<mutex>

class Application

{

std::mutex m_mutex;

bool m_bDataLoaded;

public:

Application()

{

m_bDataLoaded = false;

}

void loadData()

{

// Make This Thread sleep for 1 Second

std::this_thread::sleep_for(std::chrono::milliseconds(1000));

std::cout<<"Loading Data from XML"<<std::endl;

// Lock The Data structure

std::lock_guard<std::mutex> guard(m_mutex);

// Set the flag to true, means data is loaded

m_bDataLoaded = true;

}

void mainTask()

{

std::cout<<"Do Some Handshaking"<<std::endl;

// Acquire the Lock

m_mutex.lock();

// Check if flag is set to true or not

while(m_bDataLoaded != true)

{

  // Release the lock

  m_mutex.unlock();

  //sleep for 100 milli seconds

  std::this_thread::sleep_for(std::chrono::milliseconds(100));

  // Acquire the lock

  m_mutex.lock();

  }

  // Release the lock

  m_mutex.unlock();

  //Doc processing on loaded Data

  std::cout<<"Do Processing On loaded Data"<<std::endl;

}

};

int main()

{

  Application app;

  std::thread thread_1(&Application::mainTask, &app);

  std::thread thread_2(&Application::loadData, &app);

  thread_2.join();

  thread_1.join();

  return 0;

}

Output is as follows,

Output

It has following disadvantages,

Thread will keep on acquiring the lock and release it just to check the value, therefore it will consume CPU cycles and will also make Thread 1 slow, because it needs to acquire same lock to update the bool flag.

So obviously we need a better mechanism to achieve this, like if somehow Thread 1 could just block by waiting for an Event to get signaled and another Thread could signal that Event and make Thread 1 continue. It would have save many CPU cycles and gave better performance. But the question is how to achieve this?

We will see the answer in Option 2.

Option 2:

We can achieve this using Condition Variables.

Condition Variable is a kind Event used for signaling between 2 threads. One thread can wait for it to get signaled, while other thread can signal this.

Check out next article for detailed explanation of Conditional Variable in this Multi-threading series and solution to this problem using conditional variable.

ps:

其实主要就是获得锁,释放锁都是要陷入内核态的, 是个很重的操作. 锁虽然解决了静态条件, 但很耗CPU, 所以引入了条件变量机制, 来降低这种情况下的cpu消耗.

猜你喜欢

转载自blog.csdn.net/u201011221/article/details/83717135