Hello. I was at the interview ... As a result, I was puzzled by the following question (approximately).

Here, for example, there is a sishnaya lib in the source ... There are a lot of global variables ... But it was not written for multi-threaded applications ... It is impossible to change source codes (and the task will be too impossible)? In general, something needs to be done with global variables, but what?

  • Can you give a piece of code? didn't quite - xperious
  • Or maybe global variables in multi-thread access are used only by reading? (There, some settings that are made once at the start). Or by appointment too? Much depends on it. - AnT

2 answers 2

  • One [naive] approach is to place the calls of these functions from different threads in time , i.e. load each call to the critical section. However, keep in mind that this approach will not be applicable if the global variables in question are used to maintain state between calls to these functions. If we consider that in 9 cases out of 10 global variables are set up for just such purposes, the applicability of this approach looks questionable.

    For example (without going far beyond the example), serializing calls to the standard function strtok from different threads through the critical section does not make it workable in a multi-threaded environment, because it uses a global variable to maintain state between calls.

    (It would be interesting to argue on whether it is possible to adapt the rand() function to multithreading in this way, which, as is well known, also has a state saved between calls :))

  • The second approach is to spread the conflicts between these functions in space (in memory). Namely: declare all global variables as thread local , using the C11 _Thread_local . This does not require any significant changes to the source. (Many C pre-C11 compilers have long provided similar functionality as an extension — the same __thread in GCC or __declspec(thread) in MSVC.)

    This approach is incomparably more reliable, but again, the question is whether the situation will suit you when in each stream the library functions behave in an “isolated” way with respect to global data, i.e. whether you are satisfied, for example, isolated open file counters, isolated global status flags, etc. So the performance of this approach is also not obvious.

  • Apparently not my level, oh ... would be fumbling in these most critical sections ... and how does thread_local differ in principle from the usual local variable that we create in a function called in another thread? - xperious
  • I want to drive everything into the classroom. And it seems not a very significant change? - Qwertiy ♦

Much depends on the library itself, if the library processes data in memory, then using mutexes is an easily implemented option. But if the library works with the I / O system, then it is better to implement a separate thread for working with the library and work with it through mutexes and signaling variables.