C++ What Happens When in One Thread Write and in Second Read the Same Object? (Is It Safe)

Would a single integer be safe to read while another thread might be writing in it?

In short: no, this is UB by C++ standard and you should abide by this rule.

Longer explanation: in x86, read and writes to properly aligned memory locations no larger than word size are atomic. However, without synchronisation, compiler can optimise code in non-obvious way: caching values, reordering reads, etc. In these case you might find that changes from one thread are not visible in another at all. Other funny things might happen if you expect some thing to happen in particular order.

Use atomic<T> type. It is geared towards perfomance, and might be even lock-free on platform which supports it.

Is reading and writing to the same file thread-safe?

First of all, most standard library functions, among them all but the explicitly unlocked I/O functions, are officially thread safe. See http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_09.html. http://pubs.opengroup.org/onlinepubs/009695299/functions/flockfile.html states explicitly that flockfile() is not needed except for special demands.

A remark about the unlocked functions, which are not thread safe, is interesting:

These functions may safely be used in a multi-threaded program if and only if they are called while the invoking thread owns the ( FILE *) object, as is the case after a successful call to the flockfile() or ftrylockfile() functions.

This implies that the thread safety guarantee of the normal, locked functions is stronger than what you are doing: They are safe even when using the same FILE pointer (the result of one fopen()). It's easy to see how concurrent updating of the bookkeeping information in a FILE struct could corrupt it; the normal standard library functions guarantee not to.

On the other hand the C standard says: "Whether the same file can be simultaneously open multiple times is also implementation-defined." There is CERT advisory to avoid that. This is your use case of more than one FILE struct, obtained by two fopen() calls, potentially without an intervening fclose(), to the same underlying physical file.

That the standard makes this implementation defined may reflect (potential) limitations of certain operating systems.

A remark on the side: Trying a concurrent algorithm successfully a few times is not a guarantee that it is correct. Concurrency issues are ghastly beasts which raise their heads in a non-predictable fashion.

C++ if one thread writes toggles a bool once done, is it safe to read that bool in a loop in a single other thread?

Yes it is necessary. The rule is that if two threads could potentially be accessing the same memory at the same time, and at least one of the threads is a writer, then you have a data race. Any execution of a program with a data race has undefined behavior.

Relevant quotes from the C++14 standard:

1.10/23

The execution of a program contains a data race if it contains two potentially concurrent conflicting actions, at least one of which is not atomic, and neither happens before the other, except for the special case for signal handlers described below. Any such data race results in undefined behavior.

1.10/6

Two expression evaluations conflict if one of them modifies a memory location (1.7) and the other one accesses or modifies the same memory location.

What happens if two threads read & write the same piece of memory

The result is undefined. Corrupted data is entirely possible. For an obvious example, consider a 64-bit value being manipulated by a 32-bit processor. Let's assume the value is a simple counter, and we increment it when the lower 32-bits contain 0xffffffff. The increment produces 0x00000000. When we detect that, we increment the upper word. If, however, some other thread read the value between the time the lower word was incremented and the upper word was incremented, they get a value with an un-incremented upper word, but the lower word set to 0 -- a value completely different from what it would have been either before or after the increment is complete.

Is it safe to update an object in a thread without locks if other threads will not access it?

Short answer

No, you do not need any lock or synchronization mechanism as your problem appear to be a embarrassingly parallel task.

Longer answer

A race conditions that can only appear if two threads might access the same memory at the same time and at least one of the access is a write operation. If your program exposes this characteristic, then you need to make sure that threads access the memory in an ordered fashion. One way to do it is by using locks (it is not the only one though). Otherwise the result is UB.
It seems that you found a way to split the work among your threads s.t. each thread can work independently from the others. This is the best case scenario for concurrent programming as it does not require any synchronization. The complexity of the code is dramatically decreased and usually speedup will jump up.

Please note that as @acelent pointed out in the comment section, if you need changes made by one thread to be visible in another thread, then you might need some sort of synchronization due to the fact that depending on the memory model and on the HW changes made in one thread might not be immediately visible in the other.

This means that you might write from Thread 1 to a variable and after some time read the same memory from Thread 2 and still not being able to see the write made by Thread 1.

why reading a variable modified by other threads can be neither old value nor new value

For on example, C may be implemented on hardware which supports only 16-bit accesses to memory. In this case, loading or storing a 32-bit integer requires two load or store instructions. A thread performing these two instructions may be interrupted between their executions, and another thread may execute before the first thread is resumed. If that other thread loads, it may load one new part and one old part. If it stores, it may store both parts, and the first thread, when resumed, will see one old part and one new part. And other such mixes are possible.

Can Multiple Threads Read The Same Class Member Variable?

Can multiple threads safely read the same class member variable
without creating a race condition?

Yes and no.

Yes - The code you provided will not cause race condition, because race condition might occur when you have at least 2 threads working on the same shared resource, and at least one of those threads is writing to that resource.

No - your code isn't considered to be thread-safe, as it exposes x and y members for both read and write, and makes it possible (for you or other programmers that use your code) to cause a race condition.
You rely on your knowledge (which you might forget over time) that x should only be read, and not written to, and that y should only be written by a single thread. You should enforce this by creating mutual exclusion in the critical code sections.

If you want the threads to only read from x and y, you should make this class immutable.

c++ is unordered_mapint, Enum thread safe with one thread write and a second thread read, no new element insert?

In a nutshell: no.

Imagine that your threads are executed on different cores, and each core has the map cached in it's own cache. Even worse: each core would cache part of the map. There is no guarantee that your reading thread would see consistent values that the writing thread is updating. You still need the values to be atomic:

std::unordered_map<int, std::atomic<Status>> status_map;

Without atomics the behavior is undefined. Using atomics you still can relax the memory model if you don't need full synchronization, but at least there would be some guarantees.



Related Topics



Leave a reply



Submit