简体   繁体   中英

How to synchronize data between threads

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.

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;
}

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() << "\r\n";
            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() << "\r\n";
            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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM