Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ pointers and concurrency

I need some help for understanding general basics of shared resource access in C++ multithreading.

When I need some variable that must be accessible for several threads, I declare it as atomic, or synchronize operations with it by mutex.

But what if some function/method required pointer to type, and I must protect my variable(shared resource) for read/write in multiply threads. I know that in C and C++ pointers is passed by value, but anyway that confused me.

Question. Can I need to lock pointer to shared resource too:

void foo (int * pi = nullptr)
{
    //{..} some ops

    static std::mutex mtx;

    std::unique_lock<std::mutex> lock(mtx); // lock mutex BEFORE ptr check

    if(pi){

        ++(*pi); // dereference ptr's shared resource

    }

    lock.unlock();

    //{...} some ops
}

OR lock only for resource itself:

void foo (int * pi = nullptr)
{
    //{..} some ops
    
    static std::mutex mtx;
    
    if(pi){ // check if ptr is not null, is this thread-safe ?
       
        std::unique_lock<std::mutex> lock(mtx); // lock mutex ONLY for access shared resource itself, 
                                                // not for pointer that refers to it
        
        ++(*pi); // dereference ptr's shared resource
        
        lock.unlock();
    }


    //{...} some ops
}

Here some dumb "synthetic" example call with shared resource:

int main(){

    int __i = 0;

    std::thread t([&__i](){

        for(;;){

            foo(&__i);
            std::this_thread::sleep_for(std::chrono::milliseconds(500));
        }
    });

    for(;;){

        foo(&__i);
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        
        //std::cout << __i << std::endl;
    }

    t.join();
}

P.S. 'int' type in this example only for clarity.

like image 328
Alexander Leonov Avatar asked Oct 22 '25 15:10

Alexander Leonov


2 Answers

In your example, you don't need to lock before checking if pi is a nullptr since nothing from the outside can change what pi is pointing at. Your second example is therefore sufficient.

like image 89
Ted Lyngmo Avatar answered Oct 25 '25 06:10

Ted Lyngmo


Pointers aren't really any different from other types in this respect.

Regardless of type, multiple threads can read from the same item without synchronization, as long as none of them does any writing.

If any thread writes to shared data (again, regardless of type) you need to use a mutex (or atomic variable, etc.) to avoid race conditions.

In your case, all the threads are reading from the pointer (but never writing to it) so no mutex is needed for it.

They are modifying what the pointer refers to, so you do need a mutex for that.

like image 31
Jerry Coffin Avatar answered Oct 25 '25 05:10

Jerry Coffin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!