Will debugging change the behavior of a multithreaded program in C ++?

I am working on a multi-threaded C ++ program that deals with many synchronization issues. I am using Visual Studio 2008.

The runtime behavior of my program (the execution order of statements by threads) seems to change when I debug it using breakpoints. Can this be explained? What is the concept here? I expect the execution order to remain the same.

The second question is if Thread1 is blocked, say, by calling a wait function. Thread2 has pending statements in a ready state. Is there a situation where the program will wait for Thread1 to continue, and not to execute Thread2? I removed all the dependencies between the two threads and ensured that Thread2 was not waiting for any resource.

Rate the answers.

+6
source share
2 answers

This article on multi-threaded debugging techniques contains some good summary points on the topic:

Multithreaded errors may not be displayed when working in the debugger. Multithreading errors are very sensitive to application event times. Running the application under the debugger changes the time and, as a result, can mask problems. When your application crashes as a result of a test or worse, the client environment, but works reliably under the debugger, it is almost certainly a synchronization problem in the code.

... and more for your last last question, it is important to understand that in most cases the operating system can interrupt the execution of any of your threads whenever it pleases, even those that are "ready" to execute.

+5
source

Remember: there is no way to properly debug a multi-threaded application, as when debugging "while it does not work."

You need to have a way to somehow prove to yourself that there will be no deadlocks and that all data accesses are serialized where they should be. This is quite difficult to do, and even experienced developers may skip some cases.

Thus, it is very important that you develop a multi-threaded application, so that the design guarantees certain properties (for example, freedom from deadlocks). Note that nowhere in the previous sentence is debugging used. It should work on design, not on finding bugs.

There are two main problems:

  • Serialization of access to data structures.

  • Dead end.

The event-based or CSP approach, which I will discuss below, automatically takes care of # 1. The deadlock issue is not trivial and remains an active research topic. Namely, ways to prove the absence of a deadlock (as well as development for it!).

One example of a design that simplifies verification and formal confirmation of certain properties, such as freedom from deadlocks, is sequential process transfer (CSP) .

The CSP approach is available in most application development infrastructures and can be implemented as a system driven by nothing more than an event. Main functions:

  • Streams exchange messages (messages) among themselves.

  • Data structures are never directly shared between threads, and events themselves have data.

  • A single synchronization is performed to sequentially access the event queue when sending an event.

This in itself provides freedom from deadlocks until higher-level abstractions use event passing to reuse deadlock abstractions. For example, the problem of interlocking in the philosophy of dining philosophers can be achieved even when an event is transmitted, but now you explicitly transmit information about resources through events (messages). Thus, the problem is at least made explicit, and you are forced to think about it. The problem does not sweep under the mat, so to speak.

Formal methods for proving that no deadlocks can occur are easier to apply to code-generating events that implement CSPs. The event acceptance code can provide an introspection of the run time, which allows you to retrieve a set of received events for each state, as well as a set of states (internally this will be a state machine). This information can often be sufficient to either be unable to reach an impasse, or it can list a small set of deadlock scenarios, which can then be considered otherwise. The CSP formalism usually cannot fully capture the full semantics of software, so semantics themselves can be used to further prove that the deadlock does not occur or that they are otherwise dealt with.

+2
source

Source: https://habr.com/ru/post/920004/


All Articles