一些背景知识:
我有一个使用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语句在另一个可以打印之前打印,但我正在寻找一种不使用其他信号量的方法
答案 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());