线程同步
说明:接上一篇,注意分享线程同步的必要性和线程同步的方法。
一、什么是线程同步:
在同一时间只允许一个线程访问资源的情况称为线程同步。
二、为什么需要线程同步:
现在的计算机变得越来越多核,每一个CPU可以独立工作,但是对于内存和外部资源、数据库的访问却可能因为不同线程的访问使数据产生异常,常见的例子就是银行的转账的例子不再赘述。
三、线程同步的方法:
四、线程不安全的演示:
背景:在数据库的user_blance表插入两条数据,两人的balance值都为3000.00,整个user_balance表的balance总值为6000.00
static string connectionStr = "Server=127.0.0.1;Port=3306;Stmt=;Database=exe_dev; User=root;Password=123456"; public static void UnSafeThread() { Thread ThreadOne = new Thread(new ThreadStart(DrawMoney)); ThreadOne.Name = "A001"; Thread ThreadTwo = new Thread(new ThreadStart(DrawMoney)); ThreadTwo.Name = "A002"; ThreadOne.Start(); ThreadTwo.Start(); string sumMonney = "select sum(balance) from user_balance"; int count = 0; while (count < 200) { using (MySqlConnection conn = MySqlConnectionHelper.OpenConnection(connectionStr)) { var balance = conn.ExecuteScalar(sumMonney); Console.WriteLine("sum money:" + balance); } count++; } } private static void DoDrawMoney() { Random random = new Random(); int money = random.Next(100); string userId = Thread.CurrentThread.Name; string selectSql = "select balance from user_balance where user_id=@UserId"; string updateSql = "update user_balance set balance=@Balance+@Money where user_id=@UserId"; string updateSql2 = "update user_balance set balance=@Balance-@Money where user_id<>@UserId"; using (MySqlConnection conn= MySqlConnectionHelper.OpenConnection(connectionStr)) { var balance = conn.ExecuteScalar(selectSql, new { UserId = userId }); if (balance != null) { conn.Execute(updateSql, new { Money = money, Balance=balance, UserId = userId }); conn.Execute(updateSql2, new { Money = money, Balance = balance, UserId = userId }); } } } private static void DrawMoney() { for (int i = 0; i < 100; i++) { DoDrawMoney(); } }
运行结果:
...
sum money:6000.00
sum money:6000.00
sum money:6025.00
sum money:5975.00
sum money:6056.00
sum money:5813.00
sum money:5943.00
sum money:5681.00
sum money:5455.00
sum money:5375.00
...
程序中有三条线程在跑:两条支线程,一条主线程,主线程负责统计钱的总数,两条支线程模拟两个人赚钱,赚过来赚过去,哈哈哈,依据查询成果可以看到,钱的总数原本是6000.00,但是之后开始减少。当然上面的异常也可以通过加事务解决,或者改变sql的实现方式balance=balance+money,不过这个不是我们讨论的重点,不展开。
持续更新中...
原文:https://www.cnblogs.com/heisehenbai/p/9960978.html