首页 > 解决方案 > С# SemaphoreSlim 保证什么?它是完整的内存屏障吗?我们可以确定两个不同的信号量 Wait() 和 Release() 之间的代码是什么?

问题描述

С# SemaphoreSlim 保证什么?它是完整的内存屏障吗?我们可以确定两个不同的信号量 Wait() 和 Release() 之间的代码是什么?执行不同 SemaphoreSlim Wait()、Release() 和 Interlocked 方法和 Volatile 的序列。写/读总是在每个线程中保持顺序?

    public T Dequeue()
    {            
        canReadCountSemaphoreSlim.Wait(); 

        int i = Interlocked.Decrement(ref end);
        T val = Volatile.Read(ref buf[i]);                        

        canWriteCountSemaphoreSlim.Release();            
        return val;            
    }        
    public void Enqueue(T val)        
    {                        
        canWriteCountSemaphoreSlim.Wait();

        int i = Interlocked.Decrement(ref start);
        Volatile.Write(ref buf[i], val);

        canReadCountSemaphoreSlim.Release();            
    }

完整代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

using System.Threading;

namespace Program
{
    public class BlockingRingQueue<T> where T: class
    {
        const int BUFSIZE_LOG2 = 10;
        const int BUFSIZE = 1 << BUFSIZE_LOG2;

        T[] buf = new T[BUFSIZE];
        int start = 0;
        int end = 0;
        SemaphoreSlim canReadCountSemaphoreSlim = new SemaphoreSlim(0);
        SemaphoreSlim canWriteCountSemaphoreSlim = new SemaphoreSlim(BUFSIZE);

        public T Dequeue()
        {            
            canReadCountSemaphoreSlim.Wait();

            int i = Interlocked.Decrement(ref end);
            i = PositiveMod(i, BUFSIZE);
            T val = Volatile.Read(ref buf[i]);

            canWriteCountSemaphoreSlim.Release();            
            return val;            
        }

        public void Enqueue(T val)        
        {                        
            canWriteCountSemaphoreSlim.Wait();

            int i = Interlocked.Decrement(ref start);
            i = PositiveMod(i, BUFSIZE);
            Volatile.Write(ref buf[i], val);

            canReadCountSemaphoreSlim.Release();            
        }

        static int PositiveMod(int a, int b) => ((a % b) + b) % b;
    } 


    public class Program
    {
        const int READ_THREAD_COUNT = 3;
        static BlockingRingQueue<string> queue = new BlockingRingQueue<string>();

        public static void Main(string[] args)
        {
            new Thread(() => Pushing("ABCD")) { Name = "0" }.Start();

            for(int i = 1; i <= READ_THREAD_COUNT; i++)
                    new Thread(Poping) { Name = i.ToString() }.Start();
        }

        public static void Poping() 
        {
            while(true)
            {
                RandSpinWait();
                var val = queue.Dequeue();
                if("" == val)
                    break;

                Console.WriteLine(val + Thread.CurrentThread.Name + ' ');
            }
            //Console.WriteLine('!' + Thread.CurrentThread.Name + ' ');
        }

        public static void Pushing(string chars) 
        {
            RandSpinWait();

            var vals = chars.ToCharArray().Select(c => $"{c}")
                .Concat(Enumerable.Repeat("",READ_THREAD_COUNT));

            foreach(string v in vals)
                queue.Enqueue(v);            
        }

        public static void RandSpinWait() => Thread.SpinWait(new Random().Next(1));
    }
}

标签: c#multithreadingsemaphorelock-freememory-barriers

解决方案


推荐阅读