1.
Stream T
A
reads total _ amount, increase it to 1000 and records
the value 1100 in the global memory
2.
Stream T
in
reading total _ amount, equal to 1100, it increased to
100 in 1200 and writes the value into a global city
As a result, both contributions were successfully registered.
As you can see, the result of executing the simplest code snippet above
depends on the sequence of execution of threads in the system. This leads to
the following: in one situation the code may work, in the other - no, and in
general it is impossible to predict the occurrence of an error. This situation
is referred to
as race ( or race condition ), which is one of the most difficult
bugs captured faced by programmers. It is practically non-negotiable (since
it is unrealistic to override all possible combinations of flow execution
sequences, especially if there are many).
Attempts to bind these necessitated problems
into synchronization streams.
Immediately note that the problems of synchronization and organization of
parallel computing are some of the most difficult in practical
programming. Therefore, the development and debugging of multithreaded
programs in particular often seen as a kind of "art" that is not known to all
programmers.
In fact, such development and debugging is not an art, but a strict
discipline, subject to one basic principle: because for multithreaded
programs, traditional debugging is not suitable, the programmer must write
the code so that at the stage of development, there is room for errors. Let us
familiarize ourselves with the rules that must be followed in order for the
generated code to comply with this principle. Consider the main approaches
to competition problems.
Sometimes (but rarely enough) you can just ignore these mistakes. This
may make sense when we are not interested in the accurate recording of