Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Multithreading avoiding interleaving during function calls

int main() {
thread t1([] {printer("*", 100); });
thread t2([] {printer("+", 100); });
t1.join();
t2.join();
}

void printer(string c, int num)
{
  for (int i = 1; i <= num; i++)
  {
    cout << c;
  }
cout << endl;
}

Right now this prints something like ****+++** I want it to print *** all in one line then +++ all in one line. We are not allowed to use mutex locks or block thread access to the printer function. The code must still be multithreaded.

Any ideas on how to do this?

like image 929
bananas Avatar asked Oct 18 '17 20:10

bananas


4 Answers

Give each printer its own buffer, and print the results from the main:

void printer(ostream& oss, string c, int num) {
    for (int i = 1; i <= num; i++) {
        oss << c;
    }
}

int main() {
    stringstream s1, s2;
    thread t1([&] {printer(s1, "*", 10); });
    thread t2([&] {printer(s2, "+", 10); });
    t1.join();
    t2.join();
    cout << s1.str() << s2.str() << endl;
    return 0;
}

main prepares separate output buffers for each thread, lets each thread fill its buffer concurrently, and waits for the threads to complete. Once both threads return, main prints the results to cout.

like image 130
Sergey Kalinichenko Avatar answered Oct 12 '22 06:10

Sergey Kalinichenko


Accumulate data and then output as one shot:

void printer(string c, int num)
{
     std::string buff;
     for (int i = 1; i <= num; i++)
         buff += c;
     cout << buff << endl;
}
like image 26
Slava Avatar answered Oct 12 '22 07:10

Slava


Writing to a stringstream first instead of direct output would solve the problem of synchronization:

#include <iostream>
#include <string>
#include <sstream>
#include <thread>

void printer(std::string c, int num) {
  std::stringstream strm;    
  for (int i = 1; i <= num; i++) {
    strm << c;
  }
  std::cout << strm.str() << std::endl;
}

int main() {
  std::thread t1([] {printer("*", 100); });
  std::thread t2([] {printer("+", 100); });
  t1.join();
  t2.join();
}
like image 20
cwschmidt Avatar answered Oct 12 '22 07:10

cwschmidt


Have the main thread wait on t1 before starting t2:

thread t1([] {printer("*", 100); });
t1.join();
thread t2([] {printer("+", 100); });
t2.join();
like image 26
Hatted Rooster Avatar answered Oct 12 '22 07:10

Hatted Rooster