7

I'm asking a question about multithreading.

Say I have two global vectors,

std::vector<MyClass1*> vec1 

and

std::vector<MyClass2*> vec2. 

In addition, I have a total number of 4 threads which have access to vec1 and vec2. Can I write code as follows ?

void thread_func()
// this is the function that will be executed by a thread
{
    MyClass1* myObj1 = someFunction1(); 
    MyClass2* myObj2 = someFunction2();

    // I want to push back vec1, then push back vec2 in an atomic way
    pthread_mutex_lock(mutex);
    vec1.push_back(myObj1);
    vec2.push_back(myObj2);
    pthread_mutex_unlock(mutex);
}

for(int i=0; i<4; i++)
{
    pthread_t tid;
    pthread_create(&tid, NULL, thread_func, NULL);
}

What I want to do is that, I want to perform push_back on vec1 followed by push_back on vec2.

I'm a newbie and I have a feeling that one can only lock on one variable with a mutex. In other words, one can only put either vec1.push_back(myObj1) or vec2.push_back(myObj2) in between pthread_mutex_lock(mutex) and pthread_mutex_unlock(mutex).

I don't know if my code above is correct or not. Can someone correct me if I'm wrong?

Shawn
  • 619
  • 1
  • 5
  • 12
  • Side note: You might consider std::thread (C++11) and pass the vectors as reference (via std::ref) to the thread functions (to avoid globals). –  May 17 '15 at 17:05

2 Answers2

5

Your code is correct. The mutex is the thing being locked, not the variable(s). You lock the mutex to protect a piece of code from being executed by more than one thread, most commonly this is to protect data but in general it's really guarding a section of code.

Ron Kuper
  • 817
  • 5
  • 14
  • Are you talking about critical section ? Can you point me to some good tutorials ? – Shawn May 17 '15 at 16:28
  • 1
    https://computing.llnl.gov/tutorials/pthreads/#Mutexes talkes about mutexes, and says: Very often the action performed by a thread owning a mutex is the updating of global variables. This is a safe way to ensure that when several threads update the same variable, the final value is the same as what it would be if only one thread performed the update. The variables being updated belong to a "critical section". – Ron Kuper May 17 '15 at 16:32
  • 2
    If I just may pinpoint a potential issue: `push_back()` might raise an exception. In this case you'd loose the control over the mutex which might remain blocked for all the threads. Execute the critical secton i a try catch block. Or use `std::threads` and `std::lock_guard()` instead... – Christophe May 17 '15 at 16:44
  • Good point @Christophe, always use a RAII for mutex and as std::lock_guard is there anyway. – Surt May 17 '15 at 16:51
0

Yes, you can write like this but there are a few techniques you should definitely consider:

  1. Scoped lock pattern for exception-safety and better robustness in general. This is nicely explained in this answer
  2. Avoid globals to let optimizer work smarter for you. Try to group data into logical classes and implement locking inside it's methods. Smaller scope of variables also gives you better extensibility.
Community
  • 1
  • 1
andruso
  • 1,955
  • 1
  • 18
  • 26