.net build / pattern to block by code segment, not by thread

Is there a constructor or template in .net that defines a code segment that can be accessed by several threads, but blocks if any thread is in some other code segment (and vice versa)? For instance:

void SomeOperationA() { Block( B ) { Segment1: ... only executes if no threads are executing in Segment2 ... } } } void SomeOperationB() { Block( A ) { Segment2: ... only executes if no threads are executing in Segment1 ... } } 

Edit
Several threads must have access to segment 1 / segment2 at a time (only one segment is “active” at a time). If segment 1 is running, another thread should be able to execute segment 1, but not segment2.

Edit 2
Given all the comments / answers and my real scenario, I understand that its a little crazy to require access to Segment2 with multiple threads.

+4
source share
3 answers

This is a rather unusual model for protecting resources from improper concurrent access. . First, I would consider whether you can translate your use case into an equivalent scenario where you can use simple locks. If you could provide more details on why you need such a blocking scheme, the community might come up with other ideas.

To solve your specific question, nothing in .NET or even Win32 directly supports this blocking model , however you can create it from other primitives. I would look at using a pair of ReaderWriterLockSlim instances to protect each resource. When streams are entered into SegmentA, you get a write lock on A and a write lock on B ... and vice versa for streams included in SegmentB. This will allow multiple threads to be executed in each segment, but not at the same time .

EDIT : Given your answer in the comments on your question, I am more convinced that you need to take a look at using the Reader / Writer lock model. What you search is a way to protect a resource that when “writers” do work (serializing a dictionary), neither readers nor other authors can log in, and when “readers” do work, they don’t block each other, but block all others authors, This is a classic case for read / write locks.

EDIT 2 : now that I have more time, I think it’s worth stopping by one question. The way to think about locks is that they protect data resources (memory, files, etc.), and not areas of code. The fact that we need to identify critical sections of code that only one thread can enter at a time is an implementation detail that cannot be confused with how shared resources are used (and they need to be protected). Your question focuses on how to control which threads can go into which section of the code is redirected incorrectly from the real problem: what data resources are you trying to protect from which changes. As soon as you look at a problem from this point of view, it makes it clear which implementation paradigms make sense.

Here are some good resources for read / write lock models:

http://msdn.microsoft.com/en-us/magazine/cc163599.aspx

http://msdn.microsoft.com/en-us/library/bz6sth95.aspx

http://blogs.msdn.com/b/vancem/archive/2006/03/29/564854.aspx

+4
source

Given your editing, it seems like the correct approach would be to use ReaderWriterLockSlim , since you really shouldn't change when Segment2 is running, and you shouldn't allow more than one segment 2 to run:

 private static ReaderWriterLockSlim readerLock = new ReaderWriterLockSlim(); void SomeOperationA() { try { readerLock.EnterReadLock(); // Segment1: // ... only executes if no threads are executing in Segment2 ... } finally { readerLock.ExitReadLock(); } } void SomeOperationB() { try { readerLock.EnterWriteLock(); // Prevents multiple Segment2 from serializing, and prevents all Segment1 threads... } finally { readerLock.ExitWriteLock(); } } 
+1
source

Regarding this.

  class Segments { public const int None = 0; public const int Segm1 = 1; public const int Segm2 = 2; } int currentSegm = 0; int segm1counter = 0; int segm2counter = 0; object segm1lock = new object(); object segm2lock = new object(); void SomeOperationA() { while ( Interlocked.CompareExchange(ref currentSegm, Segments.Segm1, Segments.Segm1) != Segments.Segm1 && Interlocked.CompareExchange(ref currentSegm, Segments.Segm1, Segments.None) != Segments.None ) { Thread.Yield(); } Interlocked.Increment(ref segm1counter); try { //Segment1: //... only executes if no threads are executing in Segment2 ... } finally { lock (segm1lock) { if (Interlocked.Decrement(ref segm1counter) == 0) currentSegm = Segments.None; } } } void SomeOperationB() { while ( Interlocked.CompareExchange(ref currentSegm, Segments.Segm2, Segments.Segm2) != Segments.Segm2 && Interlocked.CompareExchange(ref currentSegm, Segments.Segm2, Segments.None) != Segments.None ) { Thread.Yield(); } Interlocked.Increment(ref segm2counter); try { //Segment2: //... only executes if no threads are executing in Segment2 ... } finally { lock (segm2lock) { if (Interlocked.Decrement(ref segm2counter) == 0) currentSegm = Segments.None; } } } 

Ok, it will not work with LockWriter lock /

0
source

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


All Articles