| ||||
| Comment on Reader Q&A: Acquire/release and sequential consistency by Tony Van Eerd
I think the important case is when b and c are global variables, possibly side-by-side in memory. Herb says “it's fine because all modern processors have single-byte reads so no need even to inject alignment/padding” Bjarne says (in the FAQ) “However, most modern processors cannot read or write a single character, it must read or write a whole word” I think the answer @Fernando is looking for is that, with concurrency now in the standard, it is up to the compiler to make sure it works. Typically that means either the processor can do single-byte reads _or_ the chars are padded/aligned. Or whatever else the compiler thinks is best (but almost definitely not locks, I hope!). I wonder what a compiler would do on a machine that doesn’t have single-byte reads, but you set alignment/packing to 1?… Read More »Comment on GotW #95: Thread Safety and Synchronization by Ralph Tandetzky
1. What is a race condition, and how serious is it? Well, a race condition is the unpredictable behavior of a piece of software due to a dependence on sequence and timing of different threads or processes. A data race is a race condition that follows from a write access to a non-atomic variable and access by an other thread (read or write) to that same variable. Access to atomic variables from multiple threads can still lead to race condition. However, as long as the end result of the program does not depend on it we’re fine and the program is correctly synchronized. 2. What is a correctly synchronized program? How do you achieve it? Be specific. A function is correctly synchronized, if the result of it does not depend on timing of threads or processes. A program is correctly synchronized if it consists of correctly synchronized functions only. That means that at least shared access to a common data amoung multiple threads must be safe: either the variables are atomic or it is ensured that while one thread writes to a location there are no accesses to the same location from other threads at the same time. Typically this is achieved by protecting the data by a mutex. 3. The types in (a)-(d) are not thread safe in the sense that concurrent read and write access is guaranteed to be without data race. Therefore, the program will not be correctly synchronized in these cases. The types in (e)-(g) are thread safe. Hence, there will be no data race as defined above. However, the execution of the program may still depend on the order in which the variable is modified and read by the two functions. Therefore, the program might be correctly synchronized but it is also possible that the program is not correctly synchronized and there’s a latent hard to detect bug. (Even though there’s no undefined behavior.) 4. (a) What is the normal external synchronization responsibility of code that owns and uses a given shared variable? The code must make sure that whenever there is a write to that variable there are no concurrent read or write accesses to it by other threads. Concurrent read accesses are allowed. 4. (b) What is the "basic thread safety guarantee" that all types must obey to enable calling code to perform normal external synchronization? All access to a This is what the standard library guarantees for all its types and functions (with only a few exceptions like 4. (c) What partial internal synchronization can still be required within the shared variable's implementation? If functions of a type access static or global data, then this access must be protected in order to provide the basic thread safety guarantee. Also different instances of a type may internally refer to some shared state. Access to that shared state must also be protected, if writes are possible. An example for this would be 5. What types should be fully internally synchronized, and why? Types that are used in order to communicate between different threads or that enable synchronization between threads such as mutexes, condition variables, futures and concurrent containers should be internally synchronized. For almost all other types internal synchronization is not necessary. There’s the so called monitor pattern which in essence turns a type providing the basic thread safety guarantee into a thread-safe type by adding a mutex and protecting every access to an instance by locking that mutex. This serializes the data accesses. Sometimes this kind of behavior is safer, but not very useful. An example are streams: E. g. writing to For normal types there is no use in making them thread-safe, but it is usually better to let the caller decide on how to synchronize access. Most types don’t need to know about multi-threading. It a bit like exceptions. Most types don’t need to worry about exceptions, they let the caller take care of them. Don’t try to give every type the responsibility of synchronizing itself. Most often it is not necessary and it only slows down the program and external synchronization, if at all necessary, is the better alternative. From my experience hardly any types need internal synchronization. Exceptions are typically types that are used for synchronization or types that have only one global instance (such as the standard output stream or particular pieces of hardware). Read More »Comment on GotW #95: Thread Safety and Synchronization by nosenseetal
@Bartosz nice A, I think Herb in 5 is aiming for stuff from his talk you dont know const and mutable… | ||||
| | ||||
| ||||
Thursday, January 9, 2014
FeedaMail: Comments for Sutterâs Mill
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment