C++11 summary 15-security issues of shared_ptr under multithreading

1. Quote

The official boost document has the following conclusions:

1) It is safe for the same shared_ptr to be "read" by multiple threads;

2) It is unsafe for the same shared_ptr to be "written" by multiple threads;

3) It is safe for different shared_ptr with shared reference count to be "written" by multiple threads;

2. Thread safety

The shared_ptr pointer class has two member variables, one is a pointer to the variable; the other is the number of times the resource is referenced. The addition and subtraction of the number of references is automatically locked and unlocked, which is thread-safe.

2.1 Reference counting

Although the reference count exists in every shared_ptr object, it actually follows the resources managed by the object. The reference count will increase as the shared_ptr object pointing to this resource increases. Therefore, reference counting is shared by all objects that point to the same piece of resource, so in fact, reference counting is implemented in the form of pointers in the bottom layer of shared_ptr, and all objects access the same space through pointers to achieve sharing.

In other words, reference counting is a critical resource, so in multithreading, we must ensure the safety of critical resource access. Therefore, before accessing the reference count in the bottom layer of shared_ptr, first lock it. When accessing After finishing, unlock it.

So the reference count of shared_ptr is thread-safe.

2.2 Resources managed by shared_ptr objects

shared_ptrThe resource managed by the object is stored on the heap, it can be accessed by multiple shared_ptr, so this is also a critical resource. Therefore, when multiple threads access it, there will be thread safety issues.

3. An example

The process of copying shared_ptr:

1) Copy the resource pointed to by the smart pointer (non-atomic operation)

2) Increase or decrease the reference count (atomic operation)

If there are the following three shared_ptr of the same type:

shared_ptr<foo> p1;                 //线程A的局部变量
shared_ptr<foo> p2(new foo);        //线程A和线程B所共享
shared_ptr<foo> p3(new foo);        //线程B的局部变量

1) At the beginning, the relationship between them can be represented by the following figure:

Insert picture description here

2) Then thread A executes the statement first: p1=p2, when executing this statement, first changes the point of ptr, and then modifies the reference count . Because it is now multi-threaded, it is very likely that such a situation may occur: when thread A finishes executing step 1, before it has time to execute step 2, it is thread B's turn to execute. As shown below:

Insert picture description here

3) Now thread B starts to execute p2=p3 without being interrupted, which means that both steps 1 and 2 are completed.
First step one:

Insert picture description here

Then step two:

Insert picture description here

Note that at this time because the reference count of the first resource is already 0, the resource will be destroyed, that is to say, after step two is executed, the ptr of p1 is a dangling pointer

Therefore, access to the resources managed by multiple shared_ptr objects is not thread-safe. If locks are not used, this will cause thread safety issues.

Conclusion: So when our multiple threads access the same shared_ptr, we should perform a lock operation.

 

Part of the reference:

https://blog.csdn.net/weixin_43850474/article/details/106328641

Guess you like

Origin blog.csdn.net/www_dong/article/details/114418454