多线程交替打印题

线程的一些交替执行题目
  1. 两个线程交替打印1-100

    • 使用两个条件变量、一个锁以及一个全局变量flag来实现
    • 两个条件变量分别等待flag变为false或者true,初始时flag为false
    • 所以初始时线程2会阻塞,当线程1执行后会修改flag为true并唤醒线程2,然后自己阻塞
    • 设置一个全局变量,每个线程打印后将其自增
    • 注意每个循环的次数为打印的次数
    #include<iostream>
    #include<vector>
    #include<thread>
    #include<mutex>
    #include<condition_variable>
    using namespace std;
    class Print
    {
    public:
        Print(int n) :timers_(n), nums_(1),flag_(false)
        {
    
        }
        void func1();
        void func2();
        void start()
        {
            thread thread1(bind(&Print::func1, this));
            thread thread2(bind(&Print::func2, this));
            thread1.join();
            thread2.join();
        }
    private:
        int                         timers_;
        bool                        flag_;
        int                         nums_;
        mutex                       mutex_;
        condition_variable          cond1_;
        condition_variable          cond2_;
    };
    void Print::func1()
    {
        for (int i = 0; i < timers_ / 2;i++)
        {
            unique_lock<mutex> lock(mutex_);
            cond1_.wait(lock, [this]()->bool{ return !this->flag_; });
            cout << nums_ << endl;
            nums_++;
            flag_ = true;
            cond2_.notify_one();
        }
    }
    
    void Print::func2()
    {
        for (int i = 0; i < timers_/2; i++)
        {
            unique_lock<mutex> lock(mutex_);
            cond2_.wait(lock, [this]()->bool{ return this->flag_; });
            cout << nums_ << endl;
            nums_++;
            flag_ = false;
            cond1_.notify_one();
        }
    }
    
    int main()
    {
        Print p(10);
        p.start();
        system("pause");
        return 0;
    }
    
  2. 两个线程交替打印1和2

    • 使用两个条件变量、一个锁以及一个全局变量flag来实现

    • 两个条件变量分别等待flag变为false或者true,初始时flag为false

    • 所以初始时线程2会阻塞,当线程1执行后会修改flag为true并唤醒线程2,然后自己阻塞

    • 注意每个循环的次数为打印的次数

    • 代码参考第一个

  3. N个线程依次打印1-n

    • 使用N个条件变量,一个锁以及一个全局计数器count来实现
    • 要实现依次打印1-n那么最好的方法当然是逐一唤醒,即1唤醒2,2唤醒3…即可
    • 但是需要注意的关键就是,第一个线程由谁去唤醒,同时最后一个线程怎么办的问题
    • 可以让主线程去唤醒第一个线程,然后逐一唤醒即可
    • 代码见下题
  4. N个线程循环打印1-n,一共循环nums次

    • 和第三题类似,只需要给线程函数加一个循环即可
    • 但是需要注意将全局计数器count循环到1
    #include<iostream>
    #include<vector>
    #include<thread>
    #include<mutex>
    #include<memory>
    #include<condition_variable>
    using namespace std;
    class Print
    {
    public:
        Print(int m, int n) :nums_(m),timers_(n), count_(0), conds_(n), threads_(n)
        {
        }
        void func1(int i);
        void func2(int i, int nums);
        void start()
        {
            for (int i = 1; i <= timers_; i++)
                threads_[i-1].reset(new thread(bind(&Print::func2, this, i, nums_)));
            func1(0);
            for (auto& val : threads_)
                val->join();
        }
    private:
        int                         nums_;
        int                         timers_;
        int                         count_;
        mutex                       mutex_;
        vector<condition_variable>  conds_;
        vector<unique_ptr<thread>>  threads_;
    };
    void Print::func1(int i)
    {
        unique_lock<mutex> lock(mutex_);
        count_++;
        conds_[i].notify_one();
    }
    
    void Print::func2(int i, int nums)
    {
        while (nums--)
        {
            unique_lock<mutex> lock(mutex_);
            conds_[i - 1].wait(lock, [this, i]()->bool{return count_ == i; });
            cout << i << endl;
            count_++;
            if (i != timers_)
                conds_[i].notify_one();
            else
            {
                count_ = 1;
                conds_[0].notify_one();
            }
        }
    }
    
    int main()
    {
        Print p(3, 10);
        p.start();
        system("pause");
        return 0;
    }
    
发布了23 篇原创文章 · 获赞 4 · 访问量 2120

猜你喜欢

转载自blog.csdn.net/hdadiao/article/details/104614728