C#-关于多线程下锁的使用,提高共享资源利用率的问题思考

前一段时间阅读某公司项目的代码,发现类的单例模式无处不在,为了控制单例全局对象属性跨线程访问到处加锁,由于每个研发人员技术及业务水平参差不齐,锁的控制范围可能会扩大化,真正需要锁住的变量利用率降低。

举例:

全局变量 int Count = 0;

定义锁对象 object CountLocker = new Object();

function1()

{

  lock(CountLocker)

  {

    Count++;

    //其他一些耗时逻辑

  }

}

这种情况下,控制计数器的锁在没有完成其他一些耗时逻辑的时候就无法得到释放,使用Count计数器的线程就一直在等待,这种靠人为因素扩大了锁的作用范围可以通过封装计数器读写自锁类型实现,只在访问计数器的时候锁住计数器

  class Program
    {
        public static Locker<int> count = new Locker<int>(0);

        static void Main(string[] args)
        {
            var watch = new Stopwatch();
            watch.Start();
            var tasks = new List<Task>();
            for (int i = 0; i < 10; i++)
            {
                var task = new Task(Add);
                tasks.Add(task);
                task.Start();
            }

            Task.WaitAll(tasks.ToArray());
            watch.Stop();
            Console.WriteLine(count.Get() + ":" + watch.ElapsedMilliseconds);

            Console.Read();
        }

        private static void Add()
        {
            for (int i = 0; i < 10000000; i++)
            {
                count.Set((ref int count) => //已经完成了对计数器的锁处理
                {
                    count++;
                });

          //其他一些耗时逻辑
} } }    public delegate void LockerSetter<T>(ref T currentValue);

  //读写互斥锁类 public sealed class Locker<T> { private readonly object locker = new object(); private T data; private Locker() { } public Locker(T rawData = default(T)) : this() { this.data = rawData; } public void Set(LockerSetter<T> setter) { lock (locker) { setter(ref data); } } public T Get() { lock (locker) { return data; } } public T Value { get { return Get(); } } }

  

posted @ 2024-03-07 15:00  孙延坤  阅读(42)  评论(0)    收藏  举报