C++11并发编程

您所在的位置:网站首页 condition_variable_any C++11并发编程

C++11并发编程

2023-01-27 22:36| 来源: 网络整理| 查看: 265

总结的很详细,打算记录下来。

原文地址:https://www.2cto.com/kf/201506/411327.html

头文件主要包含了与条件变量相关的类和函数。相关的类包括 std::condition_variable和 std::condition_variable_any,还有枚举类型std::cv_status。另外还包括函数 std::notify_all_at_thread_exit(),下面分别介绍一下以上几种类型。

std::condition_variable 类介绍

std::condition_variable是条件变量,更多有关条件变量的定义参考维基百科。Linux下使用 Pthread库中的 pthread_cond_*() 函数提供了与条件变量相关的功能, Windows 则参考 MSDN。

当 std::condition_variable对象的某个wait 函数被调用的时候,它使用 std::unique_lock(通过 std::mutex) 来锁住当前线程。当前线程会一直被阻塞,直到另外一个线程在相同的 std::condition_variable 对象上调用了 notification 函数来唤醒当前线程。

std::condition_variable 对象通常使用 std::unique_lock 来等待,如果需要使用另外的 lockable 类型,可以使用std::condition_variable_any类,本文后面会讲到 std::condition_variable_any 的用法。

?

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

#include                 // std::cout

#include                 // std::thread

#include                 // std::mutex, std::unique_lock

#include     // std::condition_variable

 

std::mutex mtx; // 全局互斥锁.

std::condition_variable cv; // 全局条件变量.

bool ready = false; // 全局标志位.

 

void do_print_id(int id)

{

    std::unique_lock lck(mtx);

    while (!ready) // 如果标志位不为 true, 则等待...

        cv.wait(lck); // 当前线程被阻塞, 当全局标志位变为 true 之后,

    // 线程被唤醒, 继续往下执行打印线程编号id.

    std::cout

    std::thread threads[10];

    // spawn 10 threads:

    for (int i = 0; i < 10; ++i)

        threads[i] = std::thread(do_print_id, i);

 

    std::cout

    for (int i = 0; i < n; ++i) {

        std::unique_lock lck(mtx);

        cv.wait(lck, shipment_available);

        std::cout

        while (shipment_available())

            std::this_thread::yield();

        std::unique_lock lck(mtx);

        cargo = i + 1;

        cv.notify_one();

    }

 

    consumer_thread.join();

 

    return 0;

}

?

1

2

3

4

5

6

7

8

9

10

1

2

3

4

5

6

7

8

9

10

std::condition_variable::wait_for() 介绍

?

1

2

3

4

5

6

7

template

  cv_status wait_for (unique_lock& lck,

                      const chrono::duration& rel_time);

 

template

       bool wait_for (unique_lock& lck,

                      const chrono::duration& rel_time, Predicate pred);

与std::condition_variable::wait() 类似,不过 wait_for可以指定一个时间段,在当前线程收到通知或者指定的时间 rel_time 超时之前,该线程都会处于阻塞状态。而一旦超时或者收到了其他线程的通知,wait_for返回,剩下的处理步骤和 wait()类似。

另外,wait_for 的重载版本的最后一个参数pred表示 wait_for的预测条件,只有当 pred条件为false时调用 wait()才会阻塞当前线程,并且在收到其他线程的通知后只有当 pred为 true时才会被解除阻塞,因此相当于如下代码:

?

1

return wait_until (lck, chrono::steady_clock::now() + rel_time, std::move(pred));

请看下面的例子(参考),下面的例子中,主线程等待th线程输入一个值,然后将th线程从终端接收的值打印出来,在th线程接受到值之前,主线程一直等待,每个一秒超时一次,并打印一个 ".":

?

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

#include            // std::cout

#include              // std::thread

#include              // std::chrono::seconds

#include               // std::mutex, std::unique_lock

#include // std::condition_variable, std::cv_status

 

std::condition_variable cv;

 

int value;

 

void do_read_value()

{

    std::cin >> value;

    cv.notify_one();

}

 

int main ()

{

    std::cout

    std::unique_lock < std::mutex > lck(mtx);

    while (cargo == 0)

        cv.wait(lck);

    std::cout

    std::thread consumers[10], producers[10];

 

    // spawn 10 consumers and 10 producers:

    for (int i = 0; i < 10; ++i) {

        consumers[i] = std::thread(consumer);

        producers[i] = std::thread(producer, i + 1);

    }

 

    // join them back:

    for (int i = 0; i < 10; ++i) {

        producers[i].join();

        consumers[i].join();

    }

 

    return 0;

}

std::condition_variable::notify_all() 介绍

唤醒所有的等待(wait)线程。如果当前没有等待线程,则该函数什么也不做。请看下面的例子:

?

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

#include                 // std::cout

#include                 // std::thread

#include                 // std::mutex, std::unique_lock

#include     // std::condition_variable

 

std::mutex mtx; // 全局互斥锁.

std::condition_variable cv; // 全局条件变量.

bool ready = false; // 全局标志位.

 

void do_print_id(int id)

{

    std::unique_lock lck(mtx);

    while (!ready) // 如果标志位不为 true, 则等待...

        cv.wait(lck); // 当前线程被阻塞, 当全局标志位变为 true 之后,

    // 线程被唤醒, 继续往下执行打印线程编号id.

    std::cout

    std::thread threads[10];

    // spawn 10 threads:

    for (int i = 0; i < 10; ++i)

        threads[i] = std::thread(do_print_id, i);

 

    std::cout

  std::unique_lock lck(mtx);

  std::notify_all_at_thread_exit(cv,std::move(lck));

  ready = true;

}

 

int main ()

{

  std::thread threads[10];

  // spawn 10 threads:

  for (int i=0; i



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3