Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .net构造/模式按代码段而不是按线程阻塞_C#_.net_Multithreading_Design Patterns_.net 4.0 - Fatal编程技术网

C# .net构造/模式按代码段而不是按线程阻塞

C# .net构造/模式按代码段而不是按线程阻塞,c#,.net,multithreading,design-patterns,.net-4.0,C#,.net,Multithreading,Design Patterns,.net 4.0,在.net中是否有一种结构或模式定义了一段代码,该段代码可以被多个线程访问,但如果任何线程位于其他代码段中(反之亦然),则会被阻塞?例如: void SomeOperationA() { Block( B ) { Segment1: ... only executes if no threads are executing in Segment2 ... } } } void SomeOperationB() {

在.net中是否有一种结构或模式定义了一段代码,该段代码可以被多个线程访问,但如果任何线程位于其他代码段中(反之亦然),则会被阻塞?例如:

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 ... 
    }     
}
编辑
多个线程应该能够同时访问段1/2(一次只有一个段处于“活动”状态)。如果段1正在执行,另一个线程应该能够执行段1,但不能执行段2。

编辑2

考虑到所有的评论/回复和我的真实场景,我意识到要求多线程访问Segment2有点疯狂。

考虑到您的编辑,似乎正确的方法应该是使用,因为在Segment2运行时您确实不应该修改集合,并且您不应该允许超过1个Segm要运行的ent2:

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();
    }
}
有点像这样

    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,这将不适用于读写器锁定//P>< P> <强>这是一个非常不寻常的模型来保护资源不正确的并发访问。< /强>我首先考虑你的用例不能转化成一个等价的场景,你可以使用简单的锁。对于锁定方案,社区可能会提供其他想法

为了解决您的具体问题,.NET甚至Win32中都不直接支持此锁定模型,但是您可以用其他原语构建它。我将考虑使用一对实例来保护每个资源。当线程进入段a时,您将在a上获得写读锁,在B上获得写锁…反之亦然这将允许多个线程在每个段内执行,但不能同时执行

编辑鉴于您在对问题的评论中的回答,我更确信您需要考虑使用读写器锁定模型。您要寻找的是一种保护资源的方法,这样当“编写者”正在工作时(序列化词典),没有读者或其他编写者可以进入,并且“读卡器”正在工作,它们不会相互阻止,而是阻止所有其他写入程序。这是读写器锁定的典型情况

编辑2:现在我有更多的时间了,我认为有一点值得详细说明。考虑锁的方式是它们保护数据资源(内存、文件等)事实上,我们需要定义一次只有一个线程可以进入的关键代码部分,这是一个实现细节,我们不应该混淆共享资源的使用方式(并且必须加以保护)。在您的问题中,重点是如何控制哪些线程可以进入与实际问题不符的代码部分:您正试图保护哪些数据资源以防发生什么样的更改。一旦您从这个角度看待问题,它将使您更清楚哪些实现范例是有意义的

这里有一些关于读写器锁定模型的好资源:


几个线程可以同时执行Segment2吗?听起来像是饥饿的处方。@SFun28:这在现实世界中的应用是什么?以下是现实世界中的场景:Segment2将ConcurrentDictionary序列化到磁盘。这种情况时有发生。序列化时,我们必须确保字典是稳定的。Segment1读取和/或r更改数据。它是线程安全的,因为ConcurrentDictionary是线程安全的。我们希望在Segment1中获得高吞吐量,但如果执行Segment2,我们希望停止显示。如果我们尝试执行Segment2,我们希望在完成Segment1执行之前保持不变。希望这有帮助。添加到我的“真实世界”"上面的场景:调用代码不会独占段1-可能段1会在一段时间内受到重击,然后调用段2,依此类推。机制只是为了安全措施。他没有说段2不能同时执行。如果是真的,简单的
lock
不会有帮助。@Andrey:是的-I如果这是一个要求,事情会变得有点棘手…对不起,我是想包括这一点。是的,两个线程应该能够同时执行段1/2(但不能同时执行两个段!)
SomeOperationB()
不能同时执行。它们应该是一样的。@Andrey:鉴于OPs对目标的评论,我不相信这是真的……我认为这不寻常的是多线程访问Segment2。如果我们说一次只有一个线程可以访问Segment2,但满足所有其他要求,我认为这只会降低到一个级别ReaderWriterLockSlim,对吗?它不适用于
ReaderWriterLockSlim
,原因如下。您不能同时输入写锁。这将成为互斥,最终只有一个线程能够执行段。如前所述,这对ReaderWriterLock不起作用。一旦您获得写锁,您就可以预写释放两个线程来模拟执行该块…@SFun28:是的,我相信这是正确的。但是,我鼓励这种减少,因为它会让你进入已知的领域,而不是在野外使用锁定。@Reed Copsey:是的,我相信你是对的。我会更新我的答案。我曾经按照这些思路思考过-但是写锁阻止两个线程同时执行,这有效地将其转化为一个“锁”调用。非常感谢您为我的原始帖子编写了一个解决方案。我现在意识到我的原始场景非常疯狂。@SFun28这是一个有趣的谜题。我没有深入了解根本原因。