Is Cout Synchronized/Thread-Safe

Is cout synchronized/thread-safe?

The C++03 standard does not say anything about it. When you have no guarantees about the thread-safety of something, you should treat it as not thread-safe.

Of particular interest here is the fact that cout is buffered. Even if the calls to write (or whatever it is that accomplishes that effect in that particular implementation) are guaranteed to be mutually exclusive, the buffer might be shared by the different threads. This will quickly lead to corruption of the internal state of the stream.

And even if access to the buffer is guaranteed to be thread-safe, what do you think will happen in this code?

// in one thread
cout << "The operation took " << result << " seconds.";

// in another thread
cout << "Hello world! Hello " << name << "!";

You probably want each line here to act in mutual exclusion. But how can an implementation guarantee that?

In C++11, we do have some guarantees. The FDIS says the following in §27.4.1 [iostream.objects.overview]:

Concurrent access to a synchronized (§27.5.3.4) standard iostream object’s formatted and unformatted input (§27.7.2.1) and output (§27.7.3.1) functions or a standard C stream by multiple threads shall not result
in a data race (§1.10). [ Note: Users must still synchronize concurrent use of these objects and streams by
multiple threads if they wish to avoid interleaved characters. — end note ]

So, you won't get corrupted streams, but you still need to synchronize them manually if you don't want the output to be garbage.

How to easily make std::cout thread-safe?

Note: This answer is pre-C++20 so it does not use std::osyncstream with its separate buffering, but uses a lock instead.

I guess you could implement your own class which wraps cout and associates a mutex with it. The operator << of that new class would do three things:

  1. create a lock for the mutex, possibly blocking other threads
  2. do the output, i.e. do the operator << for the wrapped stream and the passed argument
  3. construct an instance of a different class, passing the lock to that

This different class would keep the lock and delegate operator << to the wrapped stream. The destructor of that second class would eventually destroy the lock and release the mutex.

So any output you write as a single statement, i.e. as a single sequence of << invocations, will be printed atomically as long as all your output goes through that object with the same mutex.

Let's call the two classes synchronized_ostream and locked_ostream. If sync_cout is an instance of synchronized_ostream which wraps std::cout, then the sequence

sync_cout << "Hello, " << name << "!" << std::endl;

would result in the following actions:

  1. synchronized_ostream::operator<< would aquire the lock
  2. synchronized_ostream::operator<< would delegate the printing of "Hello, " to cout
  3. operator<<(std::ostream&, const char*) would print "Hello, "
  4. synchronized_ostream::operator<< would construct a locked_ostream and pass the lock to that
  5. locked_ostream::operator<< would delegate the printing of name to cout
  6. operator<<(std::ostream&, std::string) would print the name
  7. The same delegation to cout happens for the exclamation point and the endline manipulator
  8. The locked_ostream temporary gets destructed, the lock is released

Is writing a single string to cout thread safe in C++98

As has been pointed out in the comments, C++98 doesn't offer any notion of threads in the standard, so you can't answer this question by reference to the standard.

However any reasonable C++98 implementation intended to be used with threads (i.e., most of them outside of some embedded markets) would almost certainly offer at least a more-or-less safe std::cout for "plain" use cases. After all, using that stream for output is very common, and using it across threads in a threaded program will also be very common.

Unfortunately, that's about as much as you can say with specificity. Note, in particular, that I'm not even defining "safe" in a particular way. At least you probably expect that it won't crash, corrupt your program or produce output "out of thin air". Beyond that, it depends.

What Does it Depend On

The next step is to check the implementation itself. Hopefully you have the source1!

Typically you'll find that the implementation has some thread-agnostic code (e.g,. copying into stack-local buffers) and at some point locks and then manipulates shared state inside the std::cout object. When and where it locks is important.

Single String

For example, one would hope that the output of a single item on two threads, like std::cout << "AAAA" on thread 1 and std::cout << "BBBB" on thread 2 would at least result in "not-interleaved" output of AAAABBBB or BBBBAAAA but never BBAAAABB or something like that. This may not be true for implementations that buffer in certain ways! For example, the implementation may lock, then copy as much into an internal buffer as possible and if full, output, and then unlock and proceed again.

Keep in mind that even the std::cout object is totally locked (i.e., essentially the entire operator<<(const char *) is run under a lock), you might see interleaving of even single string output when it is run concurrently with other code that is writing to stdout but through a mechanism other than std::cout - such as printf().

In this case the C/C++ runtimes generally won't share any lock, and you'll be relying on the locking of the underlying write()-type call offered by the OS. Although this call is fully locked and thread-safe, it might not write the entire string in one shot (this is common, for example, when an intermediate buffer fills up such as when writing to a pipe).

Multiple Operators

The main problem with the stream interface is multiple operators. Something like std::cout << "AAA" << "BBB" ... is almost always turned into multiple calls on the shared std::cout object. Without external locking on your part, these are free to be interleaved in any way with other threads. Critically, this pretty much means the stream manipulators in iomanip are impossible to use safely. Something like std::cout << std::hex << 123 << std::dec will modify the stream globally, and some other thread that doesn't want hex output might run at the wrong time and get it anyways. Furthermore, the fact that the stream formatting state and flags can change in the middle of an operation may produce some weird, wonderful or downright terrible results.


1 Certainly the source is available for open source runtimes like libstc++ (used by gcc) and libc++ (used by default by LLVM on most non-Linux platforms). Microsoft appears to be providing the source for their C runtime as well.

iostream thread safety, must cout and cerr be locked separately?

If you execute this function:

void f() {
std::cout << "Hello, " << "world!\n";
}

from multiple threads you'll get a more-or-less random interleaving of the two strings, "Hello, " and "world\n". That's because there are two function calls, just as if you had written the code like this:

void f() {
std::cout << "Hello, ";
std::cout << "world!\n";
}

To prevent that interleaving, you have to add a lock:

std::mutex mtx;
void f() {
std::lock_guard<std::mutex> lock(mtx);
std::cout << "Hello, " << "world!\n";
}

That is, the problem of interleaving has nothing to do with cout. It's about the code that uses it: there are two separate function calls inserting text, so unless you prevent multiple threads from executing the same code at the same time, there's a potential for a thread switch between the function calls, which is what gives you the interleaving.

Note that a mutex does not prevent thread switches. In the preceding code snippet, it prevents executing the contents of f() simultaneously from two threads; one of the threads has to wait until the other finishes.

If you're also writing to cerr, you have the same issue, and you'll get interleaved output unless you ensure that you never have two threads making these inserter function calls at the same time, and that means that both functions must use the same mutex:

std::mutex mtx;
void f() {
std::lock_guard<std::mutex> lock(mtx);
std::cout << "Hello, " << "world!\n";
}

void g() {
std::lock_guard<std::mutex> lock(mtx);
std::cerr << "Hello, " << "world!\n";
}

Are standard output streams in C++ thread-safe (cout, cerr, clog)?

The article makes a claim about the POSIX standard for the fprintf API. It says nothing about C++ streams. And this is quite correct, as there are no such guarantees on those stream.

Note that although the logging class in that article uses C++ stream syntax, it does this via a std::ostringstream object that is created and destroyed for every logging event, and so is not shared between threads. It uses fprintf to actually write the content to the console.

The Microsoft C library makes some claims to be POSIX compliant, and so the code in the article probably is quite widely portable (as many other popular operating systems are POSIX compliant). But this doesn't mean that standard C++ streams are thread-safe.

Difference with cout and printf while multithreading in c++

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

When you use printf, your string is formatted into an internal buffer and then output to the console in a single operation ("Guest 2 waits for check-in.").

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

When you use cout, your string is output to the console in multiple parts - "Guest", followed by guestNumber, followed by " waits for check-in.", followed by endl. This is because each call to the << operator takes place as if it were a separate function call (it returns a reference to the same cout object for the next call to use).

So although writing to the console itself is thread-safe and atomic, in the cout case it's only atomic for each separate sub-string.

The solution if you don't want to use printf would be to a) use a semaphore or other locking mechanism, or b) format the text before printing it using stringstream, and then output it as a single string.

using std::cout in multiple threads

The threads are using different mutex instances as the mutex is a local variable in the exec() function so locking the mutex is pointless as each thread will be locking its own mutex resulting in no synchronization between the threads. The same mutex instance must be used by the threads to achieve synchronization.

To correct in the posted code, make the mutex a member variable. However, if another Printer object was created then there would be no synchronization between threads that used different Printer instances. In this case, the mutex would need to be a static member variable to ensure synchronization:

class Printer
{
public:
//...
private:
static std::mutex mtx_;
};

std::mutex Printer::mtx_;

To ensure a mutex is always released, regardless if a function exits normally or via an exception, use std:lock_guard:

std::lock_guard<std::mutex> lock(m); // 'm' locked, and will be
// unlocked when 'lock' is destroyed.
std::cout<< "Hello " << std::this_thread::get_id() << std::endl;
std::chrono::milliseconds duration( 100 );
std::this_thread::sleep_for( duration );

Synchronizing STD cout output multi-thread

First of all, you might consider avoiding all the explicit thread management, and instead use std::async to launch your tasks in some arbitrary number of separate threads.

Second, instead of doing the I/O in the threads themselves, you want to create results, and do the output itself serially. This means the thread function just creates some data, and leaves it to the caller to actually write that out:

std::string process(int value) {
std::ostringstream buffer;
buffer << "my" << std::setfill('0') << std::setw(2) << value;
return buffer.str();
}

Then we need to launch four copies of that asychronously:

std::vector<std::future<std::string> > results;

for (int i=0; i<4; i++)
results.push_back(std::async(std::launch::async, process, i));

Then we get the results and print them out in order:

for (auto &r : results)
std::cout << r.get() << "\n";

Putting those together, we could get code like this:

#include <string>
#include <iostream>
#include <thread>
#include <future>
#include <sstream>
#include <vector>
#include <iomanip>

std::string process(int value) {
std::ostringstream buffer;
buffer << "my" << std::setfill('0') << std::setw(2) << value;
return buffer.str();
}

int main() {
std::vector<std::future<std::string>> rets;

for (int i=0; i<4; i++)
rets.push_back(std::async(std::launch::async, process, i));

for (auto & t : rets) {
t.wait();
std::cout << t.get() << "\n";
}
}

I should add one minor point: I'm basing this on standard C++11 futures. I believe the basic idea should also work with Boost futures (upon which the standard was based) but I haven't tested that. I'd expect that some minor adjustments (e.g., to names) will be needed to work with Boost's futures.



Related Topics



Leave a reply



Submit