Search code examples
c++multithreadingloopsmutual-exclusiondata-race

How to run two loops from two threads one by one, like a flip flop?


I have a question which similarly answered here but it is not exactly what I need. I have two threads, each has a loop. Now I want to force two threads to work like a flip flop. exactly like this ABABAB or BABABA... it is not important who start first but must work one by one.

There is a very easy code I have, but it does not work well because the thread A iterates super fact and takes the lock again. Please help me as I am learning C++ multi-threading.

1- in the above link it is said that maybe it's not best approach to have two threads. Assume it is a game and I must run one iteration for player A and one iteration for Player B. I agree it does not give me much better efficiency because at each moment only one of them is working, I want to learn if there is a way.

        int pointA , pointB;
        void testA()
        {
            int i = 0;
            while (i < 10)
            {
                unique_lock<std::mutex> lck(mtx);
                cout << pointB << endl;
                pointA++;
                i++;
            }
        
        }
        
        void main()
        {
            int i = 0;
            pointA =100, pointB=0;
            thread t(testA);
            while (i < 10)
            {
                unique_lock<std::mutex> lck(mtx);
                cout << pointA << endl;
                pointB++;
                i++;
            }
    
        t.join();
    }

Solution

  • based on this answer and answer above, I managed to write the code. We need one flag to switch the turn between two loops. There is also another way with ready-go approach explained well here, it is in C# but concepts are same:

    #include <iostream>
    #include <thread>
    #include <mutex>
    
    using namespace std;
    
    mutex mutex1;
    condition_variable cv3;
    char turn;
    void ThreadA()
    {
        for (int i = 0; i < 1000; i++)
        {
            unique_lock<mutex> lock(mutex1);
            cv3.wait(lock, [] {return (turn == 'A'); });
            cout << "Thread A" << endl;
            turn = 'B';
            cv3.notify_all();
        }
    }
    
    void ThreadB()
    {
        for (int i = 0; i < 1000; i++)
        {
            unique_lock<mutex> lock(mutex1);
            cv3.wait(lock, [] {return (turn == 'B'); });
            cout << "Thread B" << endl;
            turn = 'A';
            cv3.notify_all();
        }
    }
    
    void ExecuteThreads()
    {
        turn = 'A';
        std::thread t1(ThreadA);
        std::thread t2(ThreadB);
    
        t1.join();
        t2.join();
    
        std::cout << "Finished" << std::endl;
    }
    
    int main()
    {
        ExecuteThreads();
    
        return 0;
    }