title: synchronization issue with 3 threads and 2 shared resources in c++11
body: <p>i have 3 thread and 2 shared resources, which need some locking...i tried to illustrate the resources with 2 buffers...
  - thread 1 can only access resource 1
  - thread 2 can access resource 1 and 2
  - thread 3 can access resource 1 and 2</p>
  
  <p>can someone tell me why the following locking fails? since thread2 and thread3 will access resource 1 and 2...i thought i could use try_lock? ...it seems the issue pops up, when thread2 and thread3 is only able to lock 1 mutex at a time...any idea?</p>
  
  <pre><code>#include &lt;iostream&gt; 
  #include &lt;thread&gt; 
  #include &lt;mutex&gt; 
  #include &lt;condition_variable&gt; 
  #include &lt;vector&gt; 
  #include &lt;algorithm&gt; 
  #include &lt;cassert&gt; 
  using namespace std; 
  
  class SynchronizationTest { 
  private: 
      mutex lock_r1; 
      mutex lock_r2; 
      vector&lt;pair&lt;string, int&gt;&gt; buffer_r1; 
      vector&lt;pair&lt;string, int&gt;&gt; buffer_r2; 
      unsigned int buffer_r1_max_size; 
      unsigned int buffer_r2_max_size; 
  
      bool buffer_r1_inc_element(const string &amp;thread_id) {       
          if (buffer_r1.size() == buffer_r1_max_size) { 
              return true; 
          } 
  
          if (buffer_r1.size() == 0) { 
              buffer_r1.push_back(make_pair(thread_id, 0)); 
          } 
          else { 
              int last_val = buffer_r1.back().second; 
              buffer_r1.push_back(make_pair(thread_id, ++last_val)); 
          } 
  
          return false; 
      } 
  
      bool buffer_r2_inc_element(const string &amp;thread_id) {   
          if (buffer_r2.size() == buffer_r2_max_size) { 
              return true; 
          } 
  
          if (buffer_r2.size() == 0) { 
              buffer_r2.push_back(make_pair(thread_id, 0)); 
          } 
          else { 
              int last_val = buffer_r2.back().second; 
              buffer_r2.push_back(make_pair(thread_id, ++last_val)); 
          } 
  
          return false; 
      } 
  
  public: 
      SynchronizationTest(int buff_r1_size, int buff_r2_size) : buffer_r1_max_size(buff_r1_size), 
                                                                buffer_r2_max_size(buff_r2_size) {} 
  
      void thread1() { 
          bool buffer_r1_full = false; 
  
          while (!buffer_r1_full) { 
              { 
                  unique_lock&lt;mutex&gt; l(lock_r1, std::defer_lock); 
                  if (l.try_lock()) { 
                      buffer_r1_full = buffer_r1_inc_element("thread1"); 
                  } 
              } 
  
              std::this_thread::sleep_for(std::chrono::milliseconds(10)); 
          } 
      } 
  
      void thread2() { 
          bool buffer_r1_full = false; 
          bool buffer_r2_full = false; 
  
          while (!buffer_r1_full || !buffer_r2_full) { 
              { 
                  unique_lock&lt;mutex&gt; lock1(lock_r1, defer_lock); 
                  unique_lock&lt;mutex&gt; lock2(lock_r2, defer_lock); 
  
                  int result = try_lock(lock1, lock2); 
                  if(result == -1) { 
                      buffer_r1_full = buffer_r1_inc_element("thread2"); 
                      buffer_r2_full = buffer_r2_inc_element("thread2"); 
                  } 
                  else if(result != 0) { 
                      buffer_r1_full = buffer_r1_inc_element("thread2"); 
                  } 
                  else if(result != 1) { 
                      buffer_r2_full = buffer_r2_inc_element("thread2"); 
                  } 
              } 
  
              std::this_thread::sleep_for(std::chrono::milliseconds(10)); 
          } 
      } 
  
      void thread3() { 
          bool buffer_r1_full = false; 
          bool buffer_r2_full = false; 
  
          while (!buffer_r1_full || !buffer_r2_full) { 
              { 
                  unique_lock&lt;mutex&gt; lock1(lock_r1, defer_lock); 
                  unique_lock&lt;mutex&gt; lock2(lock_r2, defer_lock); 
  
                  int result = try_lock(lock1, lock2); 
                  if(result == -1) { 
                      buffer_r1_full = buffer_r1_inc_element("thread3"); 
                      buffer_r2_full = buffer_r2_inc_element("thread3"); 
                  } 
                  else if(result != 0) { 
                      buffer_r1_full = buffer_r1_inc_element("thread3"); 
                  } 
                  else if(result != 1) { 
                      buffer_r2_full = buffer_r2_inc_element("thread3"); 
                  } 
              } 
  
              std::this_thread::sleep_for(std::chrono::milliseconds(10)); 
          } 
      } 
  
      void print_buffer() { 
          for_each(buffer_r1.begin(), buffer_r1.end(), [](pair&lt;string, int&gt; p) { cout &lt;&lt; p.first.c_str() &lt;&lt; " " &lt;&lt; p.second &lt;&lt; endl; }); 
          cout &lt;&lt; '\n'; 
          for_each(buffer_r2.begin(), buffer_r2.end(), [](pair&lt;string, int&gt; p) { cout &lt;&lt; p.first.c_str() &lt;&lt; " " &lt;&lt; p.second &lt;&lt; endl; }); 
      } 
  }; 
  
  int main() { 
      // your code goes here 
      SynchronizationTest st(20, 20); 
  
      thread t1(&amp;SynchronizationTest::thread1, &amp;st); 
      thread t2(&amp;SynchronizationTest::thread2, &amp;st); 
      thread t3(&amp;SynchronizationTest::thread3, &amp;st); 
  
      t1.join(); 
      t2.join(); 
      t3.join(); 
  
      st.print_buffer(); 
  
      return 0; 
  }
  </code></pre>