title: Producer-Consumer model
body: <p>I'm trying to simulating the producer-consumer model about multithreading.</p>
  
  <p>We assume that there three rules to obey:</p>
  
  <ol>
  <li>Producer can not add product into the bucket when the bucket is full of products.</li>
  <li>Consumer can not get product from the bucket when the bucket is empty.</li>
  <li>Producing and Consuming can not take place at the same time. In other words, the two actions are asynchronous.</li>
  </ol>
  
  <p>Now what I have:</p>
  
  <ol>
  <li>a <code>int</code> varible to store the count of products in the bucket</li>
  <li>a <code>const int</code> variable for the capacity of the bucket, which is valued as 5 in my code.</li>
  <li>a <code>int</code> variable for mutex, whose initial value is 1</li>
  <li>a <code>vector&lt;HANDLE&gt;</code> variable for suspended handle, and there will be a function scheduling these suspended threads.</li>
  </ol>
  
  <p><strong>The result is: Sometimes it work fine, but sometimes it becomes a deadlock. The code and results are as follows:</strong></p>
  
  <p><strong>code:</strong></p>
  
  <pre class="lang-cpp prettyprint-override"><code>#include &lt;iostream&gt;
  #include &lt;Windows.h&gt;
  #include &lt;vector&gt;
  
  using namespace std;
  
  // the count of product, the initial value is 0
  int product_count = 0;
  
  const int product_capacity = 5;
  
  int mutex = 1;
  
  vector&lt;HANDLE&gt; suspendedHandleVector;
  
  HANDLE GetCurrentRealHandle() {
      HANDLE realHandle = 0;
      return OpenThread(THREAD_ALL_ACCESS, TRUE, GetCurrentThreadId());
  }
  
  void ThreadScheduling() {
      if (suspendedHandleVector.size() &gt; 0) {
          HANDLE handle = suspendedHandleVector[0];
          suspendedHandleVector.erase(suspendedHandleVector.begin());
          ResumeThread(handle);
      }
  }
  
  void P() {
      --mutex;
      if (mutex &lt; 0) {
          auto handle = GetCurrentRealHandle();
          suspendedHandleVector.push_back(handle);
          SuspendThread(handle);
      }
  }
  
  void V() {
      ++mutex;
      if (mutex &gt;= 0) {
          ThreadScheduling();
      }
  }
  
  DWORD WINAPI ProducerThread(LPVOID param) {
      while (true) {
          P();
          if (product_count == product_capacity) {
              V();
              continue;
          }
          ++product_count;
          cout &lt;&lt; "I'm producer, and there are " &lt;&lt; product_count &lt;&lt; " products now" &lt;&lt; endl;
          V();
          Sleep(100);
      }
      return 0;
  }
  
  DWORD WINAPI ConsumerThread(LPVOID param) {
      while (true) {
          P();
          if (product_count == 0) {
              V();
              continue;
          }
          --product_count;
          cout &lt;&lt; "I'm consumer, and there are " &lt;&lt; product_count &lt;&lt; " products rest now" &lt;&lt; endl;
          V();
          Sleep(150);
      }
      return 0;
  }
  
  void main() {
      auto producer_handle = CreateThread(nullptr, 0, ProducerThread, nullptr, 0, nullptr);
      auto consumer_handle = CreateThread(nullptr, 0, ConsumerThread, nullptr, 0, nullptr);
      while (true) {
          cout &lt;&lt; suspendedHandleVector.size() &lt;&lt; endl; // This is for debugging
          Sleep(100);
      }
  }
  </code></pre>
  
  <p><strong>the result when it work as expected:</strong></p>
  
  <pre><code>0
  I'm producer, and there are 1 products now
  I'm consumer, and there are 0 products rest now
  0
  I'm producer, and there are 1 products now
  I'm consumer, and there are 0 products rest now
  0
  I'm producer, and there are 1 products now
  0
  I'm consumer, and there are 0 products rest now
  I'm producer, and there are 1 products now
  0
  I'm producer, and there are 2 products now
  I'm consumer, and there are 1 products rest now
  </code></pre>
  
  <p><strong>And this is a expected infinite loop. The product-count will flow at 4 and 5 because I set the producer to sleep a little more time than consumer.</strong></p>
  
  <p><strong>But here is the unexpected result:</strong></p>
  
  <pre><code>I'm producer, and there are 5 products now
  I'm consumer, and there are 4 products rest now
  0
  I'm consumer, and there are 4 products rest now
  I'm producer, and there are 5 products now
  0
  0
  I'm consumer, and there are 4 products rest now
  I'm producer, and there are 5 products now
  0
  2
  2
  2
  2
  2
  2
  </code></pre>
  
  <p><strong>As we see, the size of the suspended thread vector reached 2 from 0, which leaving out 1.</strong></p>
  
  <p><strong>Is this just a coincident where the two threads were waken up at the same then being a conflict?</strong></p>
  
  <p><strong>I consider something wrong with my code more, which needs your help.</strong></p>
  
  <p>I also got a problem during testing: How can I get the thread and then store it in the vector.</p>
  
  <p>I am not sure about using <code>OpenThread</code> to do this. My course asked me to use system call so I did'nt include <code>thread</code> headfile.</p>
  
  <p>Thank you for your help!</p>