关于单例及静态变量测试

服务端测试代码

静态类

 public class StaticClass
 {
     public static int Count = 0;
     public static int SafeCount = 0;
     public static int GetCount()
     {
         return Count++;
     }

     private static readonly object lockObj = new object();
     public static int SafeGetCount()
     {
         lock (lockObj)
         {
             return SafeCount++;
         }
     }
 }

单例服务

 public class TestSerivceSingleton : ITestSerivceSingleton
 {
     public string Name { get; set; }
     public int Count { get; set; }
     private readonly ITestSerivceTransient testSerivceTransient;

     public TestSerivceSingleton(ITestSerivceTransient testSerivceTransient)
     {
         Name = Guid.NewGuid().ToString();
         this.testSerivceTransient = testSerivceTransient;
     }
     //public TestSerivceSingleton()
     //{   
     //      Name = Guid.NewGuid().ToString();
     //}
     public string GetServiceName()
     {
         return "TestSerivceSingleton" +Name;
     }

     public string GetServiceNameChild()
     {
         return this.testSerivceTransient.GetServiceName();
     }



     public int GetCount() { return Count++; }

     private readonly object lockObj = new object();
     public int SafeCount = 0;
     public int SafeGetCount()
     {

         lock (lockObj)
         {
             return SafeCount++;
         }
     }

 }

测试代码

[Route("api/[controller]")]
[ApiController]
public class HomeController : ControllerBase
{
    private readonly ITestSerivceSingleton testSerivceSingleton;
    private readonly ITestSerivceScoped testSerivceScoped;
    private readonly ITestSerivceTransient testSerivceTransient;
    private readonly ITestSerivceSingleton testSerivceSingleton1;
    private readonly ITestSerivceScoped testSerivceScoped1;
    private readonly ITestSerivceTransient testSerivceTransient1;
    public HomeController(ITestSerivceSingleton testSerivceSingleton,ITestSerivceScoped testSerivceScoped,ITestSerivceTransient testSerivceTransient,
        ITestSerivceSingleton testSerivceSingleton1, ITestSerivceScoped testSerivceScoped1, ITestSerivceTransient testSerivceTransient1) { 
        this.testSerivceSingleton = testSerivceSingleton;
        this.testSerivceScoped = testSerivceScoped;
        this.testSerivceTransient = testSerivceTransient;
        this.testSerivceSingleton1 = testSerivceSingleton1;
        this.testSerivceScoped1 = testSerivceScoped1;
        this.testSerivceTransient1 = testSerivceTransient1;
    }

    [HttpGet("Index")]
    public IActionResult Index()
    {
       StringBuilder stringBuilder = new StringBuilder();
        #region MyRegion
        //stringBuilder.AppendLine(testSerivceSingleton.GetServiceNameBase());
        //stringBuilder.AppendLine(testSerivceSingleton.GetServiceName());
        //stringBuilder.AppendLine(testSerivceSingleton1.GetServiceName());
        //stringBuilder.AppendLine(testSerivceScoped.GetServiceNameBase());
        //stringBuilder.AppendLine(testSerivceScoped.GetServiceName());
        //stringBuilder.AppendLine(testSerivceScoped1.GetServiceName());
        //stringBuilder.AppendLine(testSerivceTransient.GetServiceNameBase());
        //stringBuilder.AppendLine(testSerivceTransient.GetServiceName());
        //stringBuilder.AppendLine(testSerivceTransient1.GetServiceName());

        //Transient作为Singleton成员
        //stringBuilder.AppendLine(testSerivceSingleton.GetServiceNameChild());
        //stringBuilder.AppendLine(testSerivceSingleton1.GetServiceNameChild());


        //Singleton作为Transient成员
        // stringBuilder.AppendLine(testSerivceTransient.GetServiceNameChild());
        // stringBuilder.AppendLine(testSerivceTransient1.GetServiceNameChild());


        //stringBuilder.AppendLine(testSerivceScoped.GetCount().ToString());
        //stringBuilder.AppendLine(testSerivceTransient.GetCount().ToString()); 
        #endregion
        stringBuilder.AppendLine($"非线程安全+单例:{testSerivceSingleton.GetCount().ToString()}");
        stringBuilder.AppendLine($"非线程安全+静态变量:{StaticClass.GetCount().ToString()}");
        stringBuilder.AppendLine($"线程安全+单例:{testSerivceSingleton.SafeGetCount().ToString()}");
        stringBuilder.AppendLine($"线程安全+静态变量:{StaticClass.SafeGetCount().ToString()}");



        return Content(stringBuilder.ToString());
    }
}

客户端模拟http请求

#region 多线程下静态变量/单例测试
#if true
await Task.Run(async () =>
{
int count = 100;
while (count >= 0)
{
Console.Clear();
await Task.Delay(100);
HttpClient httpClient = new HttpClient();
var response = await httpClient.GetAsync("http://localhost:5125/api/Home/Index");
if (response.StatusCode == HttpStatusCode.OK)
{
    var message = await response.Content.ReadAsStringAsync();
    Console.WriteLine(message);
}
count--;
}

});  
#endif
#endregion

启动WEB服务,并打开多个客户端模拟并发请求

结论

1、无论是单例对象的成员变量还是静态成员变量,所有请求都共用一个成员变量

2、在并发情况下,无论是单例对象的成员变量还是静态成员变量都存在线程安全问题

 

posted @ 2024-08-19 00:39  DaiWK  阅读(6)  评论(0编辑  收藏  举报