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