c++multithreadingc++11concurrencymutex

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.


Solution

  • 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.