C#关于加锁的多线程同步方法的代码规范

82 篇文章 3 订阅
14 篇文章 0 订阅

我们在程序开发中,经常会出现多线程中进行同步操作,比如多人抢票,多人抢红包,库存数量的更新,都需要进行局部同步操作。

使用锁对象进行同步访问的几种代码示例进行比较:

1.静态类的静态变量锁,加锁有效

2.局部类成员变量锁,加锁无效【非常严重】!

3.公共类成员变量锁,加锁有效

4.局部类静态变量锁,加锁有效

5.公共类静态变量锁,加锁有效

防止出错的解决方案:

多线程同时调用一个同步方法【需要排队执行的方法】时,为了防止出现不小心出现的【加锁无效】,请将加锁变量设置为静态的【static】

新建.net 4.6.1控制台应用程序【C#】,

新建类GlobalUtil.cs

GlobalUtil类源代码如下

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

namespace AboutLockDemo
{
    /// <summary>
    /// 公共共享变量 与 加锁、释放锁方法
    /// </summary>
    public class GlobalUtil
    {
        /// <summary>
        /// 共享变量的值
        /// </summary>
        public static int SharedVariable = 0;

        /// <summary>
        /// 复位共享变量的值
        /// </summary>
        public static void ResetSharedVariable() 
        {
            SharedVariable = 0;
        }

        /// <summary>
        /// 添加锁,进入锁
        /// </summary>
        /// <param name="lockedValue"></param>
        public static void EnterLock(ref int lockedValue) 
        {
            bool isWriteLog = false;
            while (Interlocked.Exchange(ref lockedValue, 1) != 0)
            {
                if (!isWriteLog)
                {
                    isWriteLog = true;
                    Console.WriteLine($"【{DateTime.Now.ToString("HH:mm:ss.fff")}】触发多线程同时调用接口");
                }
            }
            Console.WriteLine($"【{DateTime.Now.ToString("HH:mm:ss.fff")}】开始执行同步方法,已添加锁...");
        }

        /// <summary>
        /// 释放锁,解除锁
        /// </summary>
        /// <param name="lockedValue"></param>
        public static void ReleaseLock(ref int lockedValue) 
        {
            Interlocked.Exchange(ref lockedValue, 0);//释放锁
            Console.WriteLine($"【{DateTime.Now.ToString("HH:mm:ss.fff")}】结束执行同步方法,已释放锁...");
        }
    }
}

新建静态类LockedStaticForStaticClass.cs

LockedStaticForStaticClass类源代码如下

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

namespace AboutLockDemo
{
    /// <summary>
    /// 静态类中使用静态变量锁
    /// </summary>
    public static class LockedStaticForStaticClass
    {
        /// <summary>
        /// 加锁变量
        /// </summary>
        private static int lockedValue = 0;
        /// <summary>
        /// 加锁方法
        /// </summary>
        public static void LockedMethod() 
        {
            GlobalUtil.EnterLock(ref lockedValue);
            GlobalUtil.SharedVariable++;
            Thread.Sleep(new Random(Guid.NewGuid().GetHashCode()).Next(100, 500));
            Console.WriteLine($"【加一】以后当前共享变量的值【{GlobalUtil.SharedVariable}】");
            GlobalUtil.ReleaseLock(ref lockedValue);
        }
    }
}

新建实例化成员变量类LockedMemberForInstanceClass.cs

LockedMemberForInstanceClass源程序如下

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

namespace AboutLockDemo
{
    /// <summary>
    /// 实例化类中使用成员变量锁
    /// </summary>
    public class LockedMemberForInstanceClass
    {
        /// <summary>
        /// 加锁变量
        /// </summary>
        private int lockedValue = 0;
        /// <summary>
        /// 加锁方法
        /// </summary>
        public void LockedMethod()
        {
            GlobalUtil.EnterLock(ref lockedValue);
            GlobalUtil.SharedVariable++;
            Thread.Sleep(new Random(Guid.NewGuid().GetHashCode()).Next(100, 500));
            Console.WriteLine($"【加一】以后当前共享变量的值【{GlobalUtil.SharedVariable}】");
            GlobalUtil.ReleaseLock(ref lockedValue);
        }
    }
}

新建实例化静态成员类LockedStaticForInstanceClass.cs

LockedStaticForInstanceClass源程序如下

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

namespace AboutLockDemo
{
    /// <summary>
    /// 实例化类中使用静态对变量锁
    /// </summary>
    public class LockedStaticForInstanceClass
    {
        /// <summary>
        /// 加锁变量
        /// </summary>
        private static int lockedValue = 0;
        /// <summary>
        /// 加锁方法
        /// </summary>
        public void LockedMethod()
        {
            GlobalUtil.EnterLock(ref lockedValue);
            GlobalUtil.SharedVariable++;
            Thread.Sleep(new Random(Guid.NewGuid().GetHashCode()).Next(100, 500));
            Console.WriteLine($"【加一】以后当前共享变量的值【{GlobalUtil.SharedVariable}】");
            GlobalUtil.ReleaseLock(ref lockedValue);
        }
    }
}

在默认的Program.cs中输入测试代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AboutLockDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("--------------测试几种锁的程序写法以及具体的处理结果--------------");
            TestStaticClassLock();
            TestInstanceLocalClassLock();
            TestInstanceCommonClassLock();
            TestInstanceLocalClassStaticLock();
            TestInstanceCommonClassStaticLock();
            Console.WriteLine("多线程同时调用一个同步方法【需要排队执行的方法】时,为了防止出现不小心出现的【加锁无效】,请将加锁变量设置为静态的【static】,形如:");
            Console.WriteLine("                  private static int lockedValue = 0;");
            Console.ReadLine();
        }

        /// <summary>
        /// 静态类变量,加锁有效
        /// </summary>
        static void TestStaticClassLock() 
        {
            GlobalUtil.ResetSharedVariable();
            List<Task> tasks = new List<Task>();
            for (int i = 0; i < 3; i++)
            {
                int taskIndex = i;
                tasks.Add(Task.Run(() =>
                {
                    Console.WriteLine($"开始执行线程【{taskIndex + 1}】...");
                    LockedStaticForStaticClass.LockedMethod();
                }));
            }
            Task.WaitAll(tasks.ToArray());
            Console.WriteLine("--------------静态类的静态变量锁,加锁有效--------------");
        }

        /// <summary>
        /// 局部类成员变量锁,导致的结果是加锁无效【无法加锁的代码】
        /// </summary>
        static void TestInstanceLocalClassLock() 
        {
            GlobalUtil.ResetSharedVariable();
            List<Task> tasks = new List<Task>();
            for (int i = 0; i < 3; i++)
            {
                int taskIndex = i;
                tasks.Add(Task.Run(() =>
                {
                    Console.WriteLine($"开始执行线程【{taskIndex + 1}】...");
                    //局部变量
                    LockedMemberForInstanceClass instanceObject = new LockedMemberForInstanceClass();
                    instanceObject.LockedMethod();
                }));
            }
            Task.WaitAll(tasks.ToArray());
            Console.WriteLine("--------------局部类成员变量锁,加锁无效【非常严重】!--------------");
        }

        /// <summary>
        /// 公共类成员变量锁,加锁有效
        /// </summary>
        static void TestInstanceCommonClassLock()
        {
            GlobalUtil.ResetSharedVariable();
            //公共变量
            LockedMemberForInstanceClass instanceObject = new LockedMemberForInstanceClass();
            List<Task> tasks = new List<Task>();
            for (int i = 0; i < 3; i++)
            {
                int taskIndex = i;
                tasks.Add(Task.Run(() =>
                {
                    Console.WriteLine($"开始执行线程【{taskIndex + 1}】...");
                    instanceObject.LockedMethod();
                }));
            }
            Task.WaitAll(tasks.ToArray());
            Console.WriteLine("--------------公共类成员变量锁,加锁有效--------------");
        }

        /// <summary>
        /// 局部类静态变量锁,加锁有效
        /// </summary>
        static void TestInstanceLocalClassStaticLock()
        {
            GlobalUtil.ResetSharedVariable();
            List<Task> tasks = new List<Task>();
            for (int i = 0; i < 3; i++)
            {
                int taskIndex = i;
                tasks.Add(Task.Run(() =>
                {
                    Console.WriteLine($"开始执行线程【{taskIndex + 1}】...");
                    //局部变量
                    LockedStaticForInstanceClass instanceObject = new LockedStaticForInstanceClass();
                    instanceObject.LockedMethod();
                }));
            }
            Task.WaitAll(tasks.ToArray());
            Console.WriteLine("--------------局部类静态变量锁,加锁有效--------------");
        }

        /// <summary>
        /// 公共类静态变量锁,加锁有效
        /// </summary>
        static void TestInstanceCommonClassStaticLock()
        {
            GlobalUtil.ResetSharedVariable();
            //公共类变量
            LockedStaticForInstanceClass instanceObject = new LockedStaticForInstanceClass();
            List<Task> tasks = new List<Task>();
            for (int i = 0; i < 3; i++)
            {
                int taskIndex = i;
                tasks.Add(Task.Run(() =>
                {
                    Console.WriteLine($"开始执行线程【{taskIndex + 1}】...");
                    instanceObject.LockedMethod();
                }));
            }
            Task.WaitAll(tasks.ToArray());
            Console.WriteLine("--------------公共类静态变量锁,加锁有效--------------");
        }
    }
}

程序运行如图:

 

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯内科

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值