lock语句和线程安全

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zmq570235977/article/details/50450899
--------------以下部分内容摘自《C#高级编程(第八版)》---------------

先来看一个简单的Demo:

首先是两个类的定义

Student类,只有一个简单的Num属性

public class Student
{
public int Num { get; set; }
}
Handler类
public class Handler
{
private Student student;
public Handler(Student student)
{
this.student = student;
}
public void IncreaseNum()
{
for (int i = 0; i < 10000; i++)
{
student.Num++;
}
}
}
Main方法中创建一个Student类作为Task对象的构造函数参数。tasks是一个Task数组,程序中启动所有任务后,等待所有任务的执行完成。最后将状态值写入控制台。理论值应该是50*10000=500000.
static void Main(string[] args)
{
int taskNum = 50;
var student = new Student();
var tasks = new Task[taskNum];
for (int i = 0; i < taskNum; i++)
{
tasks[i] = Task.Run(()=>new Handler(student).IncreaseNum());
}

        for (int i = 0; i < taskNum; i++)
        {
            tasks[i].Wait(); 
        }
        Console.WriteLine("Num:{0}",student.Num);
    }

多次运行程序,并不能得到正确的值。这是因为Student类的Num属性并不是线程安全的,导致多个线程同时访问一个变量的。
要解决这个问题,必须在这个程序中添加同步的功能,可以使用lock语句。

lock语句是设置锁定和解除锁定的一种简单方式。进行了锁定后,一次只有一个线程能访问相同的实例。在lock语句块的最后,对象的锁定被解除,另一个等待锁定的线程就可以获得该锁定块了。需要注意的是,lock锁定的成员只能是引用类型,否则编译不能通过。

lock语句的使用方法:

lock(obj)
{
//do something
}
在Handler类的IncreaseNum方法中添加lock语句

public void IncreaseNum()
{
for (int i = 0; i < 10000; i++)
{
lock (student)
{
student.Num++;
}
}
}
运行程序,就可以得到正确的结果500000。
然而,这样的程序还存在一个问题:程序中所有使用Num变量的地方都必须添加lock语句块。

所以,如果要确保程序中访问Student的Num变量都是线程安全的,就必须修改Student的实现。

public class Student
{
private int num = 0;
private object syncRoot = new object();
public int Num { get { return num; } }
public int IncreaseNum()
{
lock (syncRoot)
{
return ++num;
}
}
}
同时Handler类的IncreaseNum方法也做如下改变
public void IncreaseNum()
{
for (int i = 0; i < 10000; i++)
{
this.student.IncreaseNum();
}
}
运行程序,同样可以得到正确的结果。
Student的更改采用了SyncRoot模式,通过SyncRoot模式,创建一个私有对象syncRoot,将这个对象用于lock语句。
————————————————
版权声明:本文为CSDN博主「MSP_甄心cherish」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zmq570235977/article/details/50450899

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值