描述C#多线程中lock关键字的使用分析
发布时间:2021-12-31 08:42:32
标签:C#,多线程,lock
本文介绍C# lock关键字,C#提供了一个关键字lock,它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待。
每个线程都有自己的资源,但是代码区是共享的,即每个线程都可以执行相同的函数。这可能带来的问题就是几个线程同时执行一个函数,导致数据的混乱,产生不可预料的结果,因此我们必须避免这种情况的发生。
C#提供了一个关键字lock,它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待。在C# lock关键字定义如下:
lock(expression) statement_block
expression代表你希望跟踪的对象,通常是对象引用。
如果你想保护一个类的实例,一般地,你可以使用this;如果你想保护一个静态变量(如互斥代码段在一个静态方法内部),一般使用类名就可以了。
而statement_block就是互斥段的代码,这段代码在一个时刻内只可能被一个线程执行。
下面是一个使用C# lock关键字的典型例子,在注释里说明了C# lock关键字的用法和用途。
示例如下:
using System;
using System.Threading;
namespace ThreadSimple
{
internal class Account
{
int balance; //余额
Random r=new Random();
internal Account(int initial)
{
balance=initial;
}
internal int Withdraw(int amount) //取回、取款
{
if(balance<0)
{
//如果balance小于0则抛出异常
throw new Exception("NegativeBalance");//负的 余额
}
//下面的代码保证在当前线程修改balance的值完成之前
//不会有其他线程也执行这段代码来修改balance的值
//因此,balance的值是不可能小于0的
lock(this)
{
Console.WriteLine("CurrentThread:"+Thread.CurrentThread.Name);
//如果没有lock关键字的保护,那么可能在执行完if的条件判断(成立)之后
//另外一个线程却执行了balance=balance-amount修改了balance的值
//而这个修改对这个线程是不可见的,所以可能导致这时if的条件已经不成立了
//但是,这个线程却继续执行 balance=balance-amount,所以导致balance可能小于0
if(balance>=amount)
{
Thread.Sleep(5);
balance=balance-amount;
return amount;
} else
{
return 0;
//transactionrejected
}
}
}
internal void DoTransactions()//取款事务
{
for (int i = 0; i < 100; i++)
{
Withdraw(r.Next(-50, 100));
}
}
}
internal class Test
{
static internal Thread[] threads=new Thread[10];
public static void Main()
{
Account acc=new Account(0);
for(int i=0;i<10;i++)
{
Thread t=new Thread(new ThreadStart(acc.DoTransactions));
threads[i]=t;
}
for (int i = 0; i < 10; i++)
{
threads[i].Name = i.ToString();
}
for (int i = 0; i < 10; i++)
{
threads[i].Start();
Console.ReadLine();
}
}
}
}


猜你喜欢
- 目录对zygote的理解作用启动流程启动入口脚本讲解启动过程App_main::mainAndroidRuntime::start对zygo
- FeignClient脱离eureka自定义URL需求Spring Cloud环境中的FeignClient有时候需要调用特定主机的接口,但
- 本文实例为大家分享了Android开发之自定义闹钟实现,供大家参考,具体内容如下闹钟时间设置及显示闹钟的布局很简单,就是一个简单时间设置,所
- 在上一篇文章中,我们之前对BarChart.lerp的定义并不是高效的,我们正在创建的Bar实例,仅作为Bar.lerp的参数给出,并且针对
- 首先给大家介绍一文件的上传 实体类import java.sql.Timestamp; /** * * @Decription 文件上传实体
- 找入口对 Spring 有一定基础的同学一定知道,请求入口是DispatcherServlet,所有的请求最终都会落到doDispatch方
- 1、SpringSecurity 本质是一个过滤器链SpringSecurity 采用的是责任链的设计模式,它有一条很长的过滤器链。现在对这
- 通过本文你可以用非常简短的代码替代业务逻辑中的判null校验,并且很容易的在出现空指针的时候进行打日志或其他操作。注:如果对Java8新特性
- ZXing是谷歌的一个开源库,可以用来生成二维码、扫描二维码。本文所介绍的是第一部分。首先上效果图:ZXing相关各种文件官方下载地址:ht
- Android自带的跑马灯效果不太好控制,还必须要满足条件才能有效果,而且速度不受控制。前面我的博客中有一篇就是用Android自带的跑马灯
- 本文通过JavaMailSender实现邮箱注册验证中遇到的问题开始着手,给大家详细分析了其原理以及问题的解决办法。使用邮箱注册验证,我们需
- 前言为什么用动静态库我们在实际开发中,经常要使用别人已经实现好的功能,这是为了开发效率和鲁棒性(健壮性);因为那些功能都是顶尖的工程师已经写
- 一. string的构造函数的形式:string str:生成空字符串string s(str):生成字符串为str的复制品string s
- 最近接触了Android自定义控件,涉及到自定义xml中得属性(attribute),其实也很简单,但是写着写着,发现代码不完美了,就是在a
- 话不多说,先看代码!/** * Created by david on 2017-7-5. */import com.google.gson
- 详解android 通过uri获取bitmap图片并压缩很多人在调用图库选择图片时会在onActivityResult中用Media.get
- 要求环境信息:WIN2008SERVER 开发工具:VS2015 开发语言:C#要求: 1.点击同步数据后接口获取数
- 在JavaBeans中有这样的一个描述:当一些信息需要使用类似于字典嵌套字典再嵌套列表这种很深的结构来储存的时候,请改用类来储存。实际上,这
- SpringBoot实践,开发社区登录模块今日份开启 发送邮件三个步骤:1、邮箱设置首先需要注册一个新浪邮箱 18215626061@sin
- 前言本次主要是实现一个Android应用,实现静态广播、动态广播两种改变 widget内容的方法,即在上篇博文中实验的基础上进行修改,所以此