I again have a stupid question about multithreading. As you know, multi-threaded code is fraught with many errors that are not relevant when single-threaded programming. In addition, they are very difficult to catch. It is often difficult to artificially simulate a bug that appears then disappears when the application is running, because it is difficult to predict exactly how and when exactly two different streams will access the data so that this will lead to data corruption. In addition, I probably have not yet well developed the ability to search for problematic in terms of multithreading places in the code. And now the question is: are there any recipes for how to detect potential problems of multi-threaded data access? Here, for example, lock lock. Are there any true signs by which one could say that in this code using multi-threading you need a lock and you don't need it here? Especially given the fact that the bugs associated with the use of threads is often difficult to catch? How are such problems generally localized when writing code, and how are they caught during debugging?

  • Simultaneous reading and writing of the same data from different streams clearly require synchronization. - Vladimir Martyanov
  • Very simple. You use a variable from different threads - lock is needed. Do not use - not needed. - VladD
  • The only exception is local variables in async methods. Although parts of the async method can run in different threads, synchronization is performed automatically. - VladD pm
  • 2
    Finding problems with multithreading is about as difficult as reading a text without punctuation. - andreycha
  • If you have been given an exhaustive answer, mark it as true (check next to the answer). - andreycha

2 answers 2

The first rule of multithreading - do not use multithreading :)

Locks and other types of synchronization are needed to share access to resources from different threads. Using the same object (not a class, but an object) always requires explicit or implicit locking / synchronization.

Potentially problematic places:

  • Explicit statics
  • Implicit statics (using Singleton in the code, any calls of the form SomeClass.Instance)
  • Explicit (by parameters) or implicit (through closures) objects transferred to the background thread.

Basic principles of repairing problem areas:

  • Transition to classes that explicitly support multithreading. For example, a problem from your neighboring issue is solved by replacing the linear search by searching List<DownloadTask> with a search by key in ConcurrentDictionary<Guid, DownloadTask>
  • Review of the code from the point of view "to assume that at each step another thread will take an odd thread and change everything." Lock arrangement to prevent such situations.
  • In case of problems with multithreading during data storage, shifting problems of multithreading from C # code to third-party systems (database, message queues, nosql, cache).

    multi-threaded code is fraught with many errors that are not relevant to single-threaded programming.

    There will be no mistakes if you write correctly.
    As long as there are no objects in your code that can change from different streams, this is not at all fraught.

    For fun, try creating multiple threads that just read the value of a property in an object of the next class.

     public class Mein { private int _Kalkulation; public Mein(int kalkulation) { _Kalkulation = kalkulation; } public int Kalkulation { get { return _Kalkulation; } } } 

    There will never be a problem with such an object, no matter how many threads it is read. But, as soon as you allow to change the value of a property from different streams, then problems will surely someday make themselves felt, in the form of unexpected values. Unambiguously required synchronization, if access occurs from different streams.

    Example: a bank account that can be changed by different flows. For example, an order must withdraw 100 units from the account. The stream checks the number of units on the account, gets the value 120, and while it performs some calculation, another stream removes 100 from the account and the first stream also removes 100. This is very fraught and nobody needs, as you understand.

    • 2
      There will be no mistakes if you write correctly . This applies to any topic in programming. - VladD
    • Just removed from the language. He also wanted to scoop, but he did not. Do not forget that we are programmers dependent on iron, in which there are also errors. - Berlin