0

I was going through the mutex concepts and code given in below link.

https://learn.microsoft.com/en-us/dotnet/api/system.threading.mutex?view=netcore-3.1

Can anyone let me know if there any way of forcing the threads to execute in FIFO way i.e. the thread which has requested the lock should acquire the lock first.

Are there any code examples like implementing queue for forcing FIFO for multiple thread requesting lock?

For Eg: Thread A, Thread B, Thread C are threads running.

Thread A has requested for Mutex Lock, and has acquired Lock.

Now Thread B came first and waiting to acquire Lock.

After some time Thread C also came and started waiting to acquire Lock.

But surprisingly CLR will cater Thread C instead of Thread B.

Is there any way, as per above example if i see FIFO way, the order should be Thread A, Thread B & Thread C but due to some reasons Thread A, Thread C, & Thread C are executed.

Amarnath
  • 245
  • 3
  • 4
  • 15
  • That's not what FIFO means. FIFO means that threads are allowed to do something in the order they requested it. A mutex has no order, it's one of the lowest-level synchronisation objects. In fact, if you have 3 or more threads trying to use a mutex it's quite possible you'll end up in a deadlock. You need a queue to order things – Panagiotis Kanavos Jul 27 '20 at 16:09
  • Under the hood, that .NET class uses Windows mutex support, which does not guarantee the order in any way. ("If more than one thread is waiting on a mutex, a waiting thread is selected. Do not assume a first-in, first-out (FIFO) order. External events such as kernel-mode APCs can change the wait order." https://learn.microsoft.com/en-us/windows/win32/sync/mutex-objects) – Lex Li Jul 27 '20 at 18:48
  • Thanks @ Lex Li and @Panagiotis Kanavos . Are there any examples with custom implementation to enforce FIFO way ? – Amarnath Jul 28 '20 at 04:20
  • @PanagiotisKanavos: _"if you have 3 or more threads trying to use a mutex it's quite possible you'll end up in a deadlock."_ -- untrue. The number of threads contending for a lock has no direct bearing on the likelihood of deadlock. It is entirely possible to design a system involving thousands of entities contending for a resource and yet have **zero** chance of deadlock. Deadlock comes from **unordered**, **multiple resources** all under contention. As long as you avoid those conditions, deadlock is impossible. – Peter Duniho Jul 28 '20 at 04:27
  • To the OP: your question is too broad, and off-topic (asking for recommendations, even to code examples, is off-topic). It also is hard to understand what you mean, because acquiring a lock first would inherently guarantee "FIFO" (according to your definition), as long as only one thread at a time is permitted to hold the lock (which is the case for a mutex). In other scenarios, it's impossible to guarantee because the Windows thread scheduler has the ultimate say in which thread executes first. Any runnable thread might pre-empt any other runnable thread. – Peter Duniho Jul 28 '20 at 04:31
  • @PeterDuniho : Mulitple threads might be requesting the lock, but only one thread will acquire the Lock. I have updated the question with more details. – Amarnath Jul 28 '20 at 06:45
  • @PeterDuniho quite the opposite, it's actually proven as far back as the 00s there's no way to guarantee the code will avoid deadlocks with more than 2 threads. That's why there's such an interest in lock-free containers, CSP constructs like .NET's own DataFlow and Channels, or Visual C++'s agent framework. – Panagiotis Kanavos Jul 28 '20 at 07:33
  • @PanagiotisKanavos: _"it's actually proven as far back as the 00s there's no way to guarantee the code will avoid deadlocks with more than 2 threads"_ -- you'll definitely need to provide a citation for that. Because if there's only one resource under contention, I don't see how deadlock could possibly occur. Perhaps you are confusing "deadlock" with some other thing. – Peter Duniho Jul 28 '20 at 07:38
  • Does this answer your question? [Is there a synchronization class that guarantee FIFO order in C#?](https://stackoverflow.com/q/961869) – Peter Duniho Jul 28 '20 at 07:39
  • @PeterDuniho that would be lots of articles in C++ Developers Journal (later merged into Dr Dobbs) like [this one](https://www.drdobbs.com/lock-free-data-structures/184401865). Back when Andrei Alexandrescu was still a graduate student. Also [The trouble with locks](https://www.drdobbs.com/cpp/the-trouble-with-locks/184401930) by Herb Sutter back in 2005 – Panagiotis Kanavos Jul 28 '20 at 07:46
  • @Amarnath what are you actually trying to do? What is the *actual* problem you want to solve? It's quite possible you can solve it more easily using pub/sub or a pipeline architecture. Eg, you could create an `ActionBlock` and have it process incoming messages of type `T` in a separate thread in a single line. Or you could create a pipeline of blocks, similar to a Powershell script's pipeline, to process messages asynchronously using a different thread for each step in the pipeline, while preserving order. – Panagiotis Kanavos Jul 28 '20 at 07:49
  • @PanagiotisKanavos: you're funny. There's not a single mention in either article you cite that supports your claim, in any way. Indeed, the second article clearly reiterates the conventional wisdom that deadlock cannot occur except where two or more locks are under contention, and where the locks are not taken in a consistent order. I'm done. You have failed to come anywhere close to proving your point. – Peter Duniho Jul 28 '20 at 07:51
  • @PeterDuniho : I am pretty much looking for answers for the question already asked here https://stackoverflow.com/questions/961869/is-there-a-synchronization-class-that-guarantee-fifo-order-in-c but here they are using Monitors. As per my understanding Monitors can be used with in a process. But my requirement is to use across multiple processes i think only Mutex can synchronize threads across multiple processes – Amarnath Jul 28 '20 at 07:54
  • @Amarnath I've solved ETL problems using TPL Dataflow to *avoid* depending on any kind of locking, and take advantage of buffering. It's the same architecture used by Sql Server Integration Services Dataflow tasks. An `ActionBlock` is inherently FIFO. – Panagiotis Kanavos Jul 28 '20 at 07:57
  • There is no mention in your question that you are dealing with cross-process synchronization. Don't you think that would be a _critical_ point to mention? In any case, yes...that does complicate things. Frankly, the best advice there is found in the duplicate I suggest: it is a huge code smell for you to want to order the mutex acquisition like this in the first place. It should not matter which thread (or process!) gets the mutex first...races should be able to be won arbitrarily without affecting your program logic at all. IMHO you should focus on that. – Peter Duniho Jul 28 '20 at 07:58
  • @Amarnath specifically I'm using a Dataflow pipeline (right now) to read data from multiple files at once with a `TransformBlock` that takes a path and emits its contents to the next block, a BatchBlock to batch them in batches of eg 1000 items and finally an ActionBlock that inserts those as fast as possible using SqlBulkCopy – Panagiotis Kanavos Jul 28 '20 at 07:59
  • @Amarnath you described how you thing your solution should be implemented but didn't explain what the actual problem is. The question you linked to *indirectly* mentions databases, in which case a concurrent FIFO container is necessary. A sync construct alone isn't enough. – Panagiotis Kanavos Jul 28 '20 at 08:02
  • @PanagiotisKanavos Thanks for the inputs. Will check and update. – Amarnath Jul 28 '20 at 08:50
  • @PeterDuniho : Agreed. It is a huge code smell. Will update the question with sample program with problems which i running into with Multiple Process Threads synchronization. – Amarnath Jul 28 '20 at 08:54

0 Answers0