Collaboration of the two functions through multithreading I'm going to turn them (multi-threading) to the first function after the end of the operation to notify the second function that has already finished work and the second function it received through multi-threading.

#include "stdafx.h"
#include &lt;cstdint&gt;
#include &lt;iostream&gt;
#include &lt;mutex&gt;
#include &lt;queue&gt;
#include &lt;condition_variable&gt;
#include &lt;fstream&gt; 
#include &lt;sstream&gt;
#include &lt;algorithm&gt;
std::mutex mutex;
std::queue&lt;std::string&gt; queue;
std::condition_variable conditionVariable;

void ProduceData()
{
   const char* pathToFile = "D:\\text.txt";
   std::ifstream stream(pathToFile);
   if (!stream)
   {
      std::cout &lt;&lt; "Can not open file\n";
      return;
   }

   const std::uint8_t maxWordCount = 5;
   std::string word;
   while (stream &gt;&gt; word)
   {
      std::lock_guard&lt;std::mutex&gt; lockGuard(mutex);
      for (std::uint8_t count = 0; (count &lt; maxWordCount) || (count != '\0'); ++count)
        queue.push(word);
      conditionVariable.notify_one();
   }
 }


 void ConsumeData()
 {
   while (true)
   {
    std::unique_lock&lt;std::mutex&gt; uniqueLock(mutex);
    conditionVariable.wait(uniqueLock, [] {return !queue.empty(); });
    while (!queue.empty())
    {
        const std::string&amp; str = queue.front();
        std::size_t numVowels = std::count_if(str.begin(), str.end(), isVowel);
        std::cout &lt;&lt; str &lt;&lt; "-" &lt;&lt; numVowels;
        queue.pop();
    }
    uniqueLock.unlock();
   }
}




int main()
 {
std::thread t1(ProduceData);
std::thread t2(ConsumeData);
t1.join();
t2.join();

  return 0;
 }
Your consumer thread locks out the producer for extended periods of time.

void ConsumeData()
 {
   while (true)
   {
    std::unique_lock&lt;std::mutex&gt; uniqueLock(mutex);
    conditionVariable.wait(uniqueLock, [] {return !queue.empty(); });
    while (!queue.empty())
    {
        // DO WORK
        queue.pop();
    }
    uniqueLock.unlock();
   }
}


I would rather see the consumer grab a single item from the queue then release the queue (so the producer can continue to add work while the consumer is processing a single job.

void ConsumeData()
{
    while (true)
    {
      {
        std::unique_lock&lt;std::mutex&gt; uniqueLock(mutex);
        conditionVariable.wait(uniqueLock, [] {return !queue.empty(); });

        // Note: Don't need to test queue.empty()
        //       If it is empty then the thread is re-queued on the
        //       condition variable it is only released when the test
        //       above is true.
        work = queue.front();
        queue.pop();
      }
      // You have the work item so you don't need the lock.
      // So out here you work on the item you just retrieved from
      // queue. When done you loop back around to get more work.

      // DO WORK
    }
  }
}


Your producer adds lots of items to the queue. But only signals once. You should signal once for every item added to the queue.

  for (std::uint8_t count = 0; (count &lt; maxWordCount) || (count != '\0'); ++count) {
    queue.push(word);
    conditionVariable.notify_one();
  }


As a side note:

An indent of 2 is a bit on the low side (acceptable by some). But in my opinion makes the code too cluttered.