LeetCode 1116. 打印零与奇偶数

题目链接:https://leetcode-cn.com/problems/print-zero-even-odd/

代码参考链接:https://leetcode-cn.com/problems/print-zero-even-odd/solution/c-san-chong-fang-shi-by-desaweis-imvm/

(1)原子操作解法:

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include<functional>
#include<mutex>
#include<thread>
#include<iostream>
 
using namespace std;
 
void printNumber(int value)
{
    cout << value;
}
 
class ZeroEvenOdd
{
private:
    int n;
    atomic<int> flag = 0;
 
public:
    ZeroEvenOdd(int n)
    {
        this->n = n;
    }
 
    // printNumber(x) outputs "x", where x is an integer.
    void zero(function<void(int)> printNumber)
    {
        for (int i = 1; i <= n; ++i)
        {
            while (flag != 0)
            {
                //告诉内核的调度器如果有其他进程/线程等待在这个CPU上运行,
                //则把CPU让给那些进程,即主动把时间片让出去,但如果本CPU上
                //只有我一个人在运行,没有其他人在等待运行,则调度器还是会
                //选中我来运行,也就是比较gentle的一个出让CPU。如果不执行yield,
                //则如果其他人有运行需求,则我一直尝试占着CPU运行,会导致他们的
                //响应时延变大(等到一个调度时间片后其他进程才有机会运行,现在我
                //yield了他们马上就能运行)。但如果没有其他人有需求,我可以一直占着CPU
                //(但是在过程中执行yield检查是否有其他人有运行需求)。
                //和睡眠的区别是睡眠必然等到指定时间后才重新调度我运行,
                //但yield只在其他人有运行需求的情况下才出让。
 
                this_thread::yield();
            }
 
            printNumber(0);
            if ((i & 0x1) == 0)
            {
                flag = 2;
            }
            else
            {
                flag = 1;
            }
        }
    }
 
    void even(function<void(int)> printNumber)
    {
        for (int i = 2; i <= n; i += 2)
        {
            while (flag != 2)
            {
                this_thread::yield();
            }
            printNumber(i);
            flag = 0;
        }
    }
 
    void odd(function<void(int)> printNumber)
    {
        for (int i = 1; i <= n; i += 2)
        {
            while (flag != 1)
            {
                this_thread::yield();
            }
            printNumber(i);
            flag = 0;
        }
    }
};
 
int main()
{
    ZeroEvenOdd myobj(5);
    thread myThread(&ZeroEvenOdd::zero, std::ref(myobj), printNumber);   //保证线程中用的同一个对象
    thread myThread2(&ZeroEvenOdd::even, std::ref(myobj), printNumber);
    thread myThread3(&ZeroEvenOdd::odd, std::ref(myobj), printNumber);
 
    myThread.join();
    myThread2.join();
    myThread3.join();
 
    return 0;
}

 (2)互斥锁+变量控制方法

 

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include<mutex>
#include<functional>
#include<thread>
#include<iostream>
 
using namespace std;
 
void printNumber(int value)
{
    cout << value;
}
 
class ZeroEvenOdd {
private:
    int n;
    mutex m;
    condition_variable cv;
    int flag = 0;
public:
    ZeroEvenOdd(int n) {
        this->n = n;
    }
 
    // printNumber(x) outputs "x", where x is an integer.
    void zero(function<void(int)> printNumber) {
        for (int i = 1; i <= n; ++i) {
            unique_lock<mutex> lock(m);
            cv.wait(lock, [&] {return flag == 0; });
            printNumber(0);
            if ((i & 0x1) == 0) //注意优先级,如果不确定可以加括号
            {
                flag = 2;
            }
            else {
                flag = 1;
            }
            cv.notify_all();
        }
    }
 
    void even(function<void(int)> printNumber) {
        for (int i = 2; i <= n; i += 2) {
            unique_lock<mutex> lock(m);
            cv.wait(lock, [&] {return flag == 2; });
            printNumber(i);
            flag = 0;
            cv.notify_all();
        }
    }
 
    void odd(function<void(int)> printNumber) {
        for (int i = 1; i <= n; i += 2) {
            unique_lock<mutex> lock(m);
            cv.wait(lock, [&] {return flag == 1; });
            printNumber(i);
            flag = 0;
            cv.notify_all();
        }
    }
};
 
int main()
{
    ZeroEvenOdd myobj(5);
    thread myThread(&ZeroEvenOdd::zero, std::ref(myobj), printNumber);   //保证线程中用的同一个对象
    thread myThread2(&ZeroEvenOdd::even, std::ref(myobj), printNumber);
    thread myThread3(&ZeroEvenOdd::odd, std::ref(myobj), printNumber);
 
    myThread.join();
    myThread2.join();
    myThread3.join();
 
    return 0;
}

  

posted on   xcxfury001  阅读(41)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)

导航

< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示