Home > Mobile >  Do i need synchronization in below example?
Do i need synchronization in below example?

Time:02-05

As per cppreference document:

All member functions (including copy constructor and copy assignment) can be called by multiple threads on different instances of shared_ptr without additional synchronization even if these instances are copies and share ownership of the same object.

As i understood from cppreference, you don't need to put synchronization as you are calling different member functions using different instances of shared_ptr which points to the same object. Please correct me if i understood wrong.and also give small example to understand it clearly.

#include <iostream>
#include <memory>
#include <thread>
using namespace std;

class Demo
{
public:
    int Value;
    Demo():Value(10){}

    void fun1()
    {
        for(int i=0; i<300000; i  )
        {
            Value = Value   i;
            std::cout << "Value1 :" << Value << std::endl;
        }
    }
    void fun2()
    {
        for(int i=0; i<300000; i  )
        {
            Value = Value   i;
            std::cout << "Value2 :" << Value << std::endl;
        }
    }
    void fun3()
    {
        for(int i=0; i<300000; i  )
        {
            Value = Value   i;
            std::cout << "Value3 :" << Value << std::endl;
        }
    }
};

int main()
{
    std::shared_ptr<Demo> ptr1(new Demo);
    std::thread t1(&Demo::fun1, ptr1);

    std::shared_ptr<Demo> ptr2(ptr1);
    std::thread t2(&Demo::fun2, ptr2);

    std::shared_ptr<Demo> ptr3(ptr2);
    std::thread t3(&Demo::fun3, ptr3);

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

//output:

Getting random(asynchronized) output as shown below:

 Value3 :70993659Value2 :
71000412
Value1 :71006910Value2 :
70993659Value1 :71013664

CodePudding user response:

All member functions (including copy constructor and copy assignment) can be called by multiple threads on different instances of shared_ptr without additional synchronization even if these instances are copies and share ownership of the same object.

shared_ptr's member functions can be called without synchronization. However, you still need to synchronize member function calls of the template type, i.e. Demo.

fun1, fun2 and fun3 are member of Demo, not member of shared_ptr. So you still need to use lock to protect them.

CodePudding user response:

Yes, you need synchronization for both value_ and std::cout.

Beside that, the sum of the first 300,000 positive integers is: 45,000,000,000 (45 billion). X 3 threads is: 13.5 billion. To avoid undefined behavior when a signed integer exceeds INT_MAX (2,147,483,647), it is advisable to change its data type to unsigned integer. Or to use a wider integer data type such as uint32_t and uint64_t.

#include <iostream>
#include <memory>
#include <thread>
#include <mutex>


class Demo
{
public:
    uint64_t value_;

    Demo() : value_(10) {}

    void fun1()
    {
        for (uint32_t i = 0; i < 300000; i  )
        {
            std::lock_guard lock(mutex_);

            value_  = i;
            std::cout << "Value1 :" << value_ << std::endl;
        }
    }

    void fun2()
    {
        for (uint32_t i = 0; i < 300000; i  )
        {
            std::lock_guard lock(mutex_);

            value_  = i;
            std::cout << "Value2 :" << value_ << std::endl;
        }
    }

    void fun3()
    {
        for (uint32_t i = 0; i < 300000; i  )
        {
            std::lock_guard lock(mutex_);

            value_  = i;
            std::cout << "Value3 :" << value_ << std::endl;
        }
    }

protected:
    std::mutex mutex_{};
};


int main()
{
    std::shared_ptr<Demo> ptr1(new Demo);
    std::thread t1(&Demo::fun1, ptr1);

    std::shared_ptr<Demo> ptr2(ptr1);
    std::thread t2(&Demo::fun2, ptr2);

    std::shared_ptr<Demo> ptr3(ptr2);
    std::thread t3(&Demo::fun3, ptr3);

    t1.join();
    t2.join();
    t3.join();
}
  • Related