TransWikia.com

How to synchronize data between threads

Stack Overflow Asked by Summit on December 23, 2021

This is my class to print data

class PrintData
{
    int data[20];

public:
    void setData(int dataValue[])
    {
        for( int i = 0 ; i < 20; i++)
        data[i] = dataValue[i];
    }
    void Print()
    {
        for (int i = 0; i < 20; i++)
            std::cout << data[i];

        std::cout << std::endl;
    }
};

This is the main function

int number[20] ;
void updateNumber()
{
    for (int i = 0; i < 1000; i++) {
    //  std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        for (int k = 0; k < 20; k++)
            number[k] = k;
    
        // after one iteration it should wait and after the print.Print() is executed than it should again update the data
    }
}

int main()
{
    PrintData print;
    std::thread t(&updateNumber);
    while (true)
    {
        // if upDateNumber has updated all the numbers than only than only set the number
        print.setData(number);
        
        print.Print();

    }
    return 0;
}

After iteration has finished in the thread it should wait for the print.setData(number) function to execute , once this function has executed it should again update the data.

if print.setData(number) is called and the thread is still not finished updating the array than print.setData(number) should not update the data.

2 Answers

A simple example of a producer consumer problem involving conditional variables would be something like that:

#include <thread>
#include <mutex>
#include <iostream>
#include <condition_variable>
#include <vector>
#include <unistd.h>
#define MAX_SIZE 2

struct Task
{
    std::condition_variable m_cond;
    std::mutex m_lock;
    Task(){}
};

std::vector<int> m_data;

Task m_producer;
Task m_consumers[MAX_SIZE];
std::mutex m_lock;

static bool s_Busy = false;

static void producer(void)
{

    for(;;)
    {
        size_t input=0;

        std::unique_lock<std::mutex> lock{m_lock};//{m_producer.m_lock};
        if (!s_Busy) {
            std::cout << "Enter a number: ";
            std::cin >> input;
            std::cout << "Producer waiting..." << std::this_thread::get_id() << "rn";
            m_producer.m_cond.wait(lock);
        }
        s_Busy = true;
        if (m_data.size() < input) {
            for (size_t i=0; i < input; ++i){
                m_data.push_back(i);
            }
        }
        for (int i=0; i < MAX_SIZE; ++i) {
            m_consumers[i].m_cond.notify_one();
        }
        lock.unlock();
    }

}


static void consumers(void)
{
    for(;;)
    {
        std::unique_lock<std::mutex> lock{m_lock};
        if (!s_Busy) {
            std::cout <<"Consumers waiting....!" << std::this_thread::get_id() << "rn";
            for (int i=0; i < MAX_SIZE; ++i) {
                m_consumers[i].m_cond.notify_all();
            }
        }
        if (!m_data.empty()) {
            std::cout << "Remove: " << m_data.at(0) << std::endl;
            m_data.erase(m_data.begin());
            usleep(1);
        }
        s_Busy = false;
        m_producer.m_cond.notify_one();
        lock.unlock();
    }
}


int main()
{

    std::vector<std::thread> cnsmrs;
    std::thread usr{producer};
    for (int i=0; i < MAX_SIZE; ++i)
        cnsmrs.push_back(std::thread{consumers});

    usr.join();
    for(int i=0 ; i < MAX_SIZE; ++i)
        cnsmrs.at(i).join();
    return 0;
}

You can play with different logic and implementation.

Answered by Ilian Zapryanov on December 23, 2021

I hope this help you: (semaphore is a self implementation of Qt's QSemaphore)

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


class semaphore
{
public:
    semaphore(int n = 0) : m_n(n) 
    {
    }

public:
    void acquire(int n = 1)
    {
        std::unique_lock <std::mutex> lk(m_buf_mut);

        while (m_n < n) {
            m_cv.wait(lk);
        }

        m_n -= n;

    }

    void release(int n = 1)
    {
        {
            std::unique_lock <std::mutex> lk(m_buf_mut);
            m_n += n;
        }

        m_cv.notify_all();
    }

    bool tryAcquire(int n = 1)
    {
        std::unique_lock <std::mutex> lk(m_buf_mut);

        if (m_n >= n) {
            m_n -= n;
            return true;
        }

        return false;
    }


private:
    std::mutex m_buf_mut;
    int m_n;
    std::condition_variable m_cv;
};

class PrintData
{
    int data[20];

public:
    void setData(int dataValue[])
    {
        for( int i = 0 ; i < 20; i++)
        data[i] = dataValue[i];
    }
    void Print()
    {
        for (int i = 0; i < 20; i++)
            std::cout << data[i];

        std::cout << std::endl;
    }
};


int number[20] ;
void updateNumber(semaphore *freeSem, semaphore *usedSem)
{
    for (int i = 0; i < 1000; i++) {
    //  std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    //
    
        freeSem->acquire();

        for (int k = 0; k < 20; k++)
            number[k] = k;

        usedSem->release();
    
        // after one iteration it should wait and after the print.Print() is executed than it should again update the data
    }
}

int main()
{
    PrintData print;

    semaphore freeSem(1);
    semaphore usedSem(0);

    std::thread t(&updateNumber, &freeSem, &usedSem);
    while (true)
    {
        // if upDateNumber has updated all the numbers than only than only set the number
        usedSem.acquire();
        print.setData(number);
        
        print.Print();
        freeSem.release();

    }
    return 0;
}

Answered by Ali Askari on December 23, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP