与cout和printf的区别在于c ++中的多线程

时间:2014-11-16 19:20:28

标签: c++ multithreading printf semaphore cout

一些背景知识:

我有一个使用pthreads多线程的c ++程序。该计划是一个酒店预订系统,有10位客人(每个人都有自己的主题),一个登记台(1个主题)和一个退房服务台(1个主题)。酒店只有5间客房可供客人入住。我正在使用信号量在此计划中强制执行互斥和活动订购。

问题:

这是我的代码(只是需要的部分......)

sem_init(&openRooms, 0, 5);

sem_wait(&openRooms);   //waits for there to be an open room at the hotel

cout << "Guest " << guestNumber << " waits for check-in." << endl;

sem_wait(&checkInLine); //waits for an open spot at the check-in desk

一次有5位客人可以入住酒店,因为有5间客房。当我运行程序时,我得到输出(或类似......)

Guest Guest Guest Guest 24 waits for check-in. waits for check-in.1 waits for check-in. 
3 waits for check-in.

似乎cout允许同时运行多个打印件,这就是为什么&#34; Guest&#34;连续多次打印。

我尝试过用printf做这件事,但同样的问题并没有发生。在另一个线程可以打印语句之前打印整个语句。

sem_wait(&checkInSt); //Only one person at check in receptionist at a time
printf("Guest %ld goes to the check-in receptionist.\n", my_rank);
currentThreadIn = my_rank; //Rank for receptionist to use in room assignment

输出:

Guest 1 waits for check in.
Guest 3 waits for check in.
Guest 2 waits for check in.
Guest 4 waits for check in.
Guest 0 waits for check in.

为什么会这样?是否有某种cout使用的bugger?另外,有没有办法避免使用cout?我可以使用额外的信号量来确保cout语句在另一个可以打印之前打印,但我正在寻找一种不使用其他信号量的方法

2 个答案:

答案 0 :(得分:11)

printf("Guest %ld goes to the check-in receptionist.\n", my_rank);

当您使用printf时,您的字符串将被格式化为内部缓冲区,然后通过一次操作("Guest 2 waits for check-in.")输出到控制台。

cout << "Guest " << guestNumber << " waits for check-in." << endl;

当您使用cout时,您的字符串会以多个部分输出到控制台 - "Guest",然后是guestNumber,然后是" waits for check-in.",然后是{{1 }}。这是因为对endl运算符的每次调用就像是一个单独的函数调用一样(它返回对同一个<<对象的引用,以便下次使用调用)。

因此,虽然写入控制台本身是线程安全的和原子的,但在cout情况下,它对于每个单独的子字符串只是原子的。

如果您不想使用cout,解决方法是a)使用信号量或其他锁定机制,或b)在使用printf打印文本之前格式化文本,然后输出它是一个单一的字符串。

答案 1 :(得分:0)

我也发现了同样的结果。 Printf始终有效。除非你锁定,否则我认为没有办法让cout“线程安全”。如果必须使用流来处理字符串,请考虑以下代码:

ss << "Hello World! Thread ID, " << tid << endl;
printf("%s",ss.str().c_str());