'Tried to implement Leetcode's FizzBuzz multithreading question from scratch. Getting "libc++abi.dylib: terminating" error

I started learning multithreading a few days ago because of a coming internship interview. I learned it and tried to solve Leetcode's FizzBuzz multithreading question which I could solve successfully. But then I remembered that in the first interview I was asked to code from scratch and so I tried to implement the problem. I searched the error online but couldn't figure it out.

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

class FizzBuzz
{
private:
    int n;
    int currentNum;
    std::mutex mu;
    std::condition_variable cond;
public:
    FizzBuzz(int n)
    {
        this->n = n;
        currentNum = 1;
    }

    void fizz();
    void buzz();
    void fizzbuzz();
    void number();
};

void FizzBuzz::fizz()
{
    while(currentNum <= n)
    {
        std::unique_lock<std::mutex> locker(mu);
        if (currentNum%3==0 && currentNum%5!=0)
        {
            std::cout << "Fizz" <<std::endl;
            currentNum++;
            locker.unlock();
            cond.notify_all();
        }
        else
        {
            cond.wait(locker);
        }
    }
}

void FizzBuzz::buzz()
{
    while(currentNum <= n)
    {
        std::unique_lock<std::mutex> locker(mu);
        if (currentNum%3!=0 && currentNum%5==0)
        {
            std::cout << "Buzz" <<std::endl;
            currentNum++;
            locker.unlock();
            cond.notify_all();
        }
        else
        {
            cond.wait(locker);
        }
    }
}

void FizzBuzz::fizzbuzz()
{
    while(currentNum <= n)
    {
        std::unique_lock<std::mutex> locker(mu);
        if (currentNum%3==0 && currentNum%5==0)
        {
            std::cout << "FizzBuzz" <<std::endl;
            currentNum++;
            locker.unlock();
            cond.notify_all();
        }
        else
        {
            cond.wait(locker);
        }
    }
}

void FizzBuzz::number()
{
    while(currentNum <= n)
    {
        std::unique_lock<std::mutex> locker(mu);
        if (currentNum%3==0 && currentNum%5!=0)
        {
            std::cout << currentNum <<std::endl;
            currentNum++;
            locker.unlock();
            cond.notify_all();
        }
        else
        {
            cond.wait(locker);
        }
    }
}


int main()
{
    FizzBuzz fb(15);
    std::thread t1 (&FizzBuzz::fizz, &fb);
    std::thread t2 (&FizzBuzz::buzz, &fb);
    std::thread t3 (&FizzBuzz::fizzbuzz, &fb);
    std::thread t4 (&FizzBuzz::number, &fb);
    t1.join();
    t2.join();
    t3.join();
    t4.join();
    return 0;
}

If you have other tips for me to improve myself, let me know. I'm new to multithreading. Trying to learn as much as possible.

EDIT: Added the join() statements for all the threads. Now it's getting into a deadlock.



Solution 1:[1]

In your FizzBuzz::number() the first if condition should be: "if (currentNum%3!=0 && currentNum%5!=0)" not "if (currentNum%3==0 && currentNum%5!=0)"

Solution 2:[2]

You are not calling join() on any of your threads. This will cause the application to terminate when the std::thread objects are destroyed.

Add

t4.join();
t3.join();
t2.join();
t1.join();

to the end of your main function. This will wait until the threads finish before exiting the program.

Solution 3:[3]

Consider what happens when currentNum = 1 (your first value): currentNum % 3 == 0 and currentNum % 5 == 0 are both false. All threads end up waiting forever.

You should add this condition to some thread:

if (currentNum % 3 != 0 && currentNum % 5 != 0)

Solution 4:[4]

Change the condition for the function printing number

if (currentNum % 3 != 0 && currentNum % 5 != 0) {
 ...
}

it works

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 asio_guy
Solution 2 Anthony Williams
Solution 3 VLL
Solution 4 Nyamkhuu Buyanjargal