1

Consider following code:

#include <iostream> 
#include <mutex> 
#include <thread> 
#include <vector> 
#include <chrono>
using namespace std; 
const int SIZE = 10;

mutex myMutex;
std::vector<int> strange;

void add_to_vector(int i) { 
   lock_guard<mutex> g(myMutex);

   if (strange.size() < 100) {
       cout << "Dodaje do bazy" << i << std::endl;
       strange.push_back(i);
       cout << "Dodałem do bazy" << i << std::endl;
   }

} 
void f(int n) { 
    while (strange.size() < 100)
    {
    add_to_vector(n);
    std::this_thread::sleep_for(std::chrono::microseconds(100));
}
} 
 int main()
 {
     thread t1(f, 1); // 0-9 
     thread t2(f, 2); // 10-19 
     thread t3(f, 3); // 20-29 
     thread t4(f, 4); // 30-39 
     thread t5(f, 5); // 40-49 

     t1.join();
     t2.join();
     t3.join();
     t4.join();
     t5.join();

     for (auto a : strange) {
         std::cout << a << ", ";
     }
     return 0;
 }

Is threads waiting to mutex unlock, lining up ? It seems that after unlocking , access to resources gets a random thread. How to ensure that they get access to the resource threads in FIFO order ?

sweet_sugar
  • 1,390
  • 3
  • 13
  • 22
  • Yeah, that's the point of threads that they can do things in not necessarily serial order. What is your question? – milleniumbug Apr 04 '15 at 15:44
  • As a rule of thumb ensure unlocking multiple mutexes in the same order they've been locked, to avoid deadlocks. – πάντα ῥεῖ Apr 04 '15 at 15:47
  • 3
    Btw, was it intentional that `while (strange.size() < 100)` is outside the purview of any lock protection? – WhozCraig Apr 04 '15 at 15:51
  • 1
    The standard mutexes does not guarantee fifo order, but you can e.g. implement a [ticket lock](http://stackoverflow.com/a/8384692/126769). Though you might still have an underlying problem that some threads arn't blocked on the mutex while another thread does its work and re-acquires it (i.e. there would be a race between unlocking and locking the mutex, or who locks the mutex first, unless your threads also run under a fifo scheduler) – nos Apr 04 '15 at 16:09
  • I don't want to invoke it in very specific order. When threads are fighting for the resource, after unlocking mutex I want to access a resource getting another from the queue just like a queue in the supermarket to avoid starvation. @WhozCraig function add_to_vector has lock protection, I want to each thread make add_to_vector many times but not indefinitely. – sweet_sugar Apr 04 '15 at 18:43
  • 2
    @sweet_sugar you're missing my point. `size()` is not some magic atomic member function. Assessing `strange.size()` as you are invokes a race condition. Regardless of the order you want these to execute in, that evaluation is unprotected and a recipe for a race-condition. You'd be better off using `while (add_to_vector(n) < 100)` and having `add_to_vector` latch the mutex, perform the assessment, and return `strange.size()` pulled while under the confines of the latch. – WhozCraig Apr 04 '15 at 18:59
  • @WhozCraig You're right. – sweet_sugar Apr 04 '15 at 19:30

0 Answers0