C#-多线程数据同步容易出现的异常问题

来源:互联网 发布:cms摄像头监控软件设置 编辑:程序博客网 时间:2024/05/16 06:12

问题描述:

当多个线程同时并发读写数据库的时候会抛出异常,这是比较典型的多线程并发同步所带来的问题,因为集合在读的过程中是不容许我们修改的,因此就需要引入锁的概念,加上读写锁就不会出现问题。


集合类通常不是线程安全的,多个阅读器可以安全的读取集合.但是对集合的任何修改都将为访问集合的所有线程生成不明确的结果.使用以下任何方法都可以令集合类是线程安全的
(1) 使用Synchronized 方法,则从该类派生包装,并通过该包装以独占方式访问集合
(2) 如果该类没有Synchronized 方法,则从该类派生并使用SyncRoot属性实现Synchronized 方法.
(3) 在访问该集合时对SyncRoot属性使用锁定机制
这一段时间在公司做多线程的东西比较多,所以把一些心得写了下来,对关注这一块的朋友有个提示作用.
大家可以看看以下代码:

  class Program    {        static void Main(string[] args)        {            Program pg = new Program();            //写线程            Thread t1 = new System.Threading.Thread(new ThreadStart(pg.t1fun));            // 读线程            Thread t2 = new System.Threading.Thread(new ThreadStart(pg.t2fun));            //删线程            Thread t3 = new System.Threading.Thread(new ThreadStart(pg.t3fun));            t1.Start();            t2.Start();            t3.Start();        }        ArrayList arraylist = new ArrayList();        public void t1fun()        {            while (true)            {                arraylist.Add("t1--写入");                System.Console.Out.WriteLine("写入");                System.Threading.Thread.Sleep(1000);            }        }        public void t2fun()        {            while (true)            {                for (int i = arraylist.Count - 1; i >= 0; i--)                {                    System.Console.Out.WriteLine("t2读取:"+(string)arraylist[i]);                }                System.Threading.Thread.Sleep(1000);            }        }        public void t3fun()        {            while (true)            {                for (int i = arraylist.Count - 1; i >= 0; i--)                {                    arraylist.RemoveAt(i);                    System.Console.Out.WriteLine("t3删除:t1"+i.ToString());                }                System.Threading.Thread.Sleep(1000);            }        }    }

这个测试程序得简单,大家一看就明白了你可以运行一下看看,程序一会就挂了,揭示异常:未处理的异常: System.ArgumentOutOfRangeException: 索引超出范围。必须为非负值并小于集合大小。
这就是因为多线程中对共享的集合资源同步引起的
下面是改后的代码:

 class Program    {        static void Main(string[] args)        {            Program pg = new Program();            //写线程            Thread t1 = new System.Threading.Thread(new ThreadStart(pg.t1fun));            // 读线程            Thread t2 = new System.Threading.Thread(new ThreadStart(pg.t2fun));            //删线程            Thread t3 = new System.Threading.Thread(new ThreadStart(pg.t3fun));            t1.Start();            t2.Start();            t3.Start();        }        ArrayList arraylist = new ArrayList();        public void t1fun()        {            while (true)            {                 lock (arraylist.SyncRoot)                {                    arraylist.Add("t1--写入");                }                System.Console.Out.WriteLine("写入");                System.Threading.Thread.Sleep(1000);            }        }        public void t2fun()        {            while (true)            {                lock (arraylist.SyncRoot)                {                    for (int i = arraylist.Count - 1; i >= 0; i--)                    {                        System.Console.Out.WriteLine("t2读取:" + (string)arraylist[i]);                    }                }                System.Threading.Thread.Sleep(1000);            }        }        public void t3fun()        {            while (true)            {                lock (arraylist.SyncRoot)                {                    for (int i = arraylist.Count - 1; i >= 0; i--)                    {                        arraylist.RemoveAt(i);                        System.Console.Out.WriteLine("t3删除:t1" + i.ToString());                    }                }                System.Threading.Thread.Sleep(1000);            }        }    }
0 0
原创粉丝点击