mirror of
https://github.com/isocpp/CppCoreGuidelines.git
synced 2025-12-18 21:24:41 +03:00
Closed #108.
This commit is contained in:
@@ -9383,15 +9383,39 @@ See also:
|
|||||||
It is hard to be certain that concurrency isn't used now or sometime in the future.
|
It is hard to be certain that concurrency isn't used now or sometime in the future.
|
||||||
Code gets re-used.
|
Code gets re-used.
|
||||||
Libraries using threads my be used from some other part of the program.
|
Libraries using threads my be used from some other part of the program.
|
||||||
|
Note that this applies most urgently to library code and least urgently to stand-alone applications.
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
???
|
double cached_computation(double x)
|
||||||
|
{
|
||||||
|
static double cached_x = 0.0;
|
||||||
|
static double cached_result = COMPUTATION_OF_ZERO;
|
||||||
|
double result;
|
||||||
|
|
||||||
|
if (cached_x = x)
|
||||||
|
return cached_result;
|
||||||
|
result = computation(x);
|
||||||
|
cached_x = x;
|
||||||
|
cached_result = result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Although `cached_computation` works perfectly in a single-threaded environment, in a multi-threaded environment the two `static` variables result in data races and thus undefined behavior.
|
||||||
|
|
||||||
|
There are several ways that this example could be made safe for a multi-threaded environment:
|
||||||
|
* Delegate concurrency concerns upwards to the caller.
|
||||||
|
* Mark the `static` variables as `thread_local` (which might make caching less effective).
|
||||||
|
* Implement concurrency control, for example, protecting the two `static` variables with a `static` lock (which might reduce performance).
|
||||||
|
* Have the caller provide the memory to be used for the cache, thereby delegating both memory allocation and concurrency concerns upwards to the caller.
|
||||||
|
* Refuse to build and/or run in a multi-threaded environment.
|
||||||
|
* Provide two implementations, one which is used in single-threaded environments and another which is used in multi-threaded environments.
|
||||||
|
|
||||||
**Exception**: There are examples where code will never be run in a multi-threaded environment.
|
**Exception**: There are examples where code will never be run in a multi-threaded environment.
|
||||||
However, there are also many examples where code that was "known" to never run in a multi-threaded program
|
However, there are also many examples where code that was "known" to never run in a multi-threaded program
|
||||||
was run as part of a multi-threaded program. Often years later.
|
was run as part of a multi-threaded program. Often years later.
|
||||||
Typically, such programs lead to a painful effort to remove data races.
|
Typically, such programs lead to a painful effort to remove data races.
|
||||||
|
Therefore, code that is never intended to run in a multi-threaded environment should be clearly labeled as such.
|
||||||
|
|
||||||
### <a name="Rconc-races"></a> CP.2: Avoid data races
|
### <a name="Rconc-races"></a> CP.2: Avoid data races
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user