单例下并发的情况下访问私有变量的一个典型问题

Posted 凯帝农垦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例下并发的情况下访问私有变量的一个典型问题相关的知识,希望对你有一定的参考价值。

一个小问题,单例下 并发的情况下访问私有变量的典型问题,以下是一个小Demo

public class dssd
    {
        static void Main(string[] args)
        {
            var t = Task.Factory.StartNew(() =>
            {
                Thread.Sleep(1000);
                var obj2 = ImportProvider.Instance;
                
                Arg ds = new Arg() { TypeSS = 2 };
                obj2.Import(ds);
                        
            });

            var obj = ImportProvider.Instance;

            obj.Import(new Arg() { TypeSS = 1 });
                                
            Console.Read();
        }    
    }


    public interface IImportProvider
    {
        string Import(Arg args);
    }

    public class ImportProvider : IImportProvider
    {
        #region 单例
        public static readonly IImportProvider _instance = new ImportProvider();

        private ImportProvider() { }

        public static IImportProvider Instance { get { return _instance; } }
        #endregion

        public string Import(Arg args)
        {
            Yaya = new List<int>() { args.TypeSS };
            HSSFWorkbook workBook = new HSSFWorkbook() { dddd =args.TypeSS};

            if (args.TypeSS==1)
            {
                Thread.Sleep(5000);
                Console.WriteLine(Yaya[0]);               
            }        
            
            return "ssss";
        }

        private List<int> Yaya = new List<int>();

    }

   


    public class HSSFWorkbook
    {
        public int dddd { get; set; }    
    }

    public class Arg
    {
        public int TypeSS { get; set; }

    }

毫无疑问,第一个输出的 2,

因为在 Thread.Sleep(5000);

之后,Yaya[0]的值被 t线程走的代码给改了,这是单例下,私有变量遇到的一个常见的问题。在并发线程访问的情况下,她们是共享私有变量的,像上面这种情况,主线程中获取到了开启的工作线程改后变量值,问题典型,所以标一下
改后:

public class dssd
    {


        static void Main(string[] args)
        {
            List<int> Yaya = new List<int>();

            var t = Task.Factory.StartNew(() =>
            {
                Thread.Sleep(1000);
                var obj2 = ImportProvider.Instance;
                
                Arg ds = new Arg() { TypeSS = 2 };
                obj2.Import(ds, Yaya);

            });

            var obj = ImportProvider.Instance;

            obj.Import(new Arg() { TypeSS = 1 }, Yaya);                      
          
            Console.Read();
        }

    }


    public interface IImportProvider
    {
        string Import(Arg args, List<int> ww);
    }

    public class ImportProvider : IImportProvider
    {
        #region 单例
        public static readonly IImportProvider _instance = new ImportProvider();

        private ImportProvider() { }

        public static IImportProvider Instance { get { return _instance; } }
        #endregion

        public string Import(Arg args,List<int> ww)
        {
            ww = new List<int>() { args.TypeSS };
            HSSFWorkbook workBook = new HSSFWorkbook() { dddd =args.TypeSS};

            if (args.TypeSS==1)
            {
                Thread.Sleep(5000);
                Console.WriteLine(ww[0]);               
            }        
            
            return "ssss";
        }

    }

   


    public class HSSFWorkbook
    {
        public int dddd { get; set; }    
    }

    public class Arg
    {
        public int TypeSS { get; set; }

    }

 输出:1

以上是关于单例下并发的情况下访问私有变量的一个典型问题的主要内容,如果未能解决你的问题,请参考以下文章

java ThreadLocal线程设置私有变量底层源码分析

阿里一面:Spring Bean 默认是单例的,高并发情况下,如何保证并发安全?

Java并发-了解线程安全

并发编程之单例模式,volatile和 synchronized

阿里一面:Spring Bean 默认是单例的,高并发情况下,如何保证并发安全?

阿里一面:Spring Bean 默认是单例的,高并发情况下,如何保证并发安全?