-1

I have a MyClassArray[fixed lentgh N] of MyClass that I want to guarantee thread safe access for each element. I don't want to lock the entire array whenever I need to work with one element. I am wondering if a same sized lockArray of lock object where whenever I want to access element i from MyClassArray I do Monitor.Enter(lockArray[i]) the access to MyClassArray[i] would be thread safe. My concern is if concurrent access to lockArray[i] could mess it up. Sorry if this is too naive or if there is another easy solution for this problem. I am new on multi-thread and C#.

Rgds, Christiano

  • Use a dedicated locking object, don't lock on the array itself. [Overview of synchronization primitives](https://learn.microsoft.com/dotnet/standard/threading/overview-of-synchronization-primitives) & [Synchronizing data for multithreading](https://learn.microsoft.com/dotnet/standard/threading/synchronizing-data-for-multithreading) & [How does lock work exactly?](https://stackoverflow.com/questions/6029804/how-does-lock-work-exactly) & [Monitor And Lock In C# (C-SharpCorner)](https://www.c-sharpcorner.com/UploadFile/de41d6/monitor-and-lock-in-C-Sharp/). –  Sep 24 '20 at 16:23
  • Whether it's safe depends greatly on the specifics of what you're doing and how it's implemented. No one can accurately state the correctness of code that hasn't even been written yet. – Servy Sep 24 '20 at 16:30
  • @OlivierRogier The question does not suggest locking on any arrays directly. That said, it would really only be a concern if it was exposed outside of the class handling its synchronization. – Servy Sep 24 '20 at 16:33
  • @Servy, my doubt is if two threads are exact at the same time trying to do Monitor.Enter(lockArray[i]) if that would work and guarantee that only one thread will have the access until the Monitor.Exit. Or if I need to do this Monitor.Enter(lockArray[i]) inside a static lock{} block. – Christiano Pereira Sep 24 '20 at 16:40
  • @ChristianoPereira And without actually seeing the specifics, no one can correctly answer that question. – Servy Sep 24 '20 at 16:44

1 Answers1

0

Assuming that you have two same-sized arrays values and locks:

int[] values = Enumerable.Range(0, 100).ToArray();
object[] locks = Enumerable.Range(0, 100).Select(_ => new object()).ToArray();

...and you want to protect each element of values with the corresponding element of locks:

lock (locks[13])
{
    values[13] += 1;
}

...this is perfectly thread-safe, provided that:

  1. The initialization of the locks array will occur before starting the threads or tasks that will do the processing. Otherwise you may have visibility issues (solvable with the Thread.MemoryBarrier and other means, but you'd better avoid that complexity).

  2. Each element of the values array can be mutated independently from the others. Otherwise, if you find the need to create nested locks like this:

    lock (locks[13])
        lock (locks[14])
            values[13] += values[14];

...then you are probably in trouble (you may have to solve the Five Dining philosophers problem in order to prevent deadlocks).

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104