线程基础三 使用C#中的lock关键词
C#中lock关键字主要是为确保当一个线程使用某些资源时,同时无法其他线程无法使用该资源。下面我们看看下面的小例子。
static void Main(string[] args)
{
var c = new Counter();
var t1 = new Thread(() => TestCounter(c));
var t2 = new Thread(() => TestCounter(c));
var t3 = new Thread(() => TestCounter(c));
t1.Start();
t2.Start();
t3.Start();
t1.Join();
t2.Join();
t3.Join();
Console.WriteLine($"Total count:{c.Count}");
Console.WriteLine("----------------------"); var c1 = new CounterWithLock();
t1 = new Thread(() => TestCounter(c1));
t2 = new Thread(() => TestCounter(c1));
t3 = new Thread(() => TestCounter(c1));
t1.Start();
t2.Start();
t3.Start();
t1.Join();
t2.Join();
t3.Join();
Console.WriteLine($"Total count:{c1.Count}"); }
static void TestCounter(CounterBase c)
{
for (int i = ; i < ; i++)
{
c.Increment();
c.Decrement();
}
}
public abstract class CounterBase
{
public abstract void Increment(); public abstract void Decrement();
}
public class Counter:CounterBase
{
public int Count { get; private set; }
public override void Increment()
{
Count++;
}
public override void Decrement()
{
Count--;
} }
public class CounterWithLock : CounterBase
{
private readonly object _syncRoot = new object();
public int Count { get; private set; }
public override void Increment()
{
lock (_syncRoot)
{
Count++;
}
}
public override void Decrement()
{
lock (_syncRoot)
{
Count--;
}
}
}
下面是输出结果,可以看到输出结果并非我们所期望的0,当然结果可能为0,但大多数情况下都不是。
在这个例子中,当主程序启动时,创建了一个Counter对象。该类定义了一个可以递增和递减的简单计数器。然后我们启动了三个线程。这三个线程共享一个counter实例,在一个周期中进行一次递增和递减。这将导致不确定的结果。如果多次运行程序,则会打印出多种不同的计数器值。
这是因为Counter类并不是线程安全的。当多个线程同时访问Counter对象时,第一个线程得到的Counter值10并增加为11。然后第二个进程得到的值是11并增加到12.第一个线程得到的Counter值12递减为11并保存在Counter中,同时第二个线程也执行了相同的操作。结果我们进行了两次递增操作但是有效的递减只有一次,这显然不对。这种情形被称为竞争条件(race condition)。竞争条件是多线程环境中非常常见的错误原因。
为了确保不会发生以上情形,必须保证当有线程操作counter对象时,所有其他线程必须等待知道当前线程完成操作。我们可以使用lock关键词来实现这种行为。如果锁定了一个对象,需要访问该对象的所有线程都会处于阻塞状态,并等待直到该对象解除锁定。当然这有可能导致严重的性能问题,针对这一问题,我们后面再讲。
线程基础三 使用C#中的lock关键词的更多相关文章
- Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) JAVA日志的前世今生 .NET MVC采用SignalR更新在线用户数 C#多线程编程系列(五)- 使用任务并行库 C#多线程编程系列(三)- 线程同步 C#多线程编程系列(二)- 线程基础 C#多线程编程系列(一)- 简介
Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) 一.前言 由于本篇文章较长,所以下面给出内容目录方便跳转阅读,当然也可以用博客页面最右侧的文章目录导航栏进行跳转查阅. 一.前言 ...
- C#中的线程(三)多线程
C#中的线程(三)多线程 Keywords:C# 线程Source:http://www.albahari.com/threading/Author: Joe AlbahariTranslator ...
- 线程基础:JDK1.5+(9)——线程新特性(中)
(接上文<线程基础:JDK1.5+(8)--线程新特性(上)>) 3.工作在多线程环境下的"计数器": 从这个小节開始,我们将以一个"赛跑"的样例. ...
- Java基础_线程的使用及创建线程的三种方法
线程:线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务. 进程:进 ...
- java中线程的三种实现方式
一下记录下线程的3中实现方式:Thread,Runnable,Callable 不需要返回值时,建议使用Runnable:有返回值时建议使用Callable 代码如下所示: package com.f ...
- Java中终止线程的三种方法
终止线程一般建议采用的方法是让线程自行结束,进入Dead(死亡)状态,就是执行完run()方法.即如果想要停止一个线程的执行,就要提供某种方式让线程能够自动结束run()方法的执行.比如设置一个标志来 ...
- Java基础加强之并发(三)Thread中start()和run()的区别
Thread中start()和run()的区别 start() : 它的作用是启动一个新线程,新线程会执行相应的run()方法.start()不能被重复调用.run() : run()就和普通的成 ...
- java编程基础篇---------> 编写一个程序,从键盘输入三个整数,求三个整数中的最小值。
编写一个程序,从键盘输入三个整数,求三个整数中的最小值. 关键:声明变量temp 与各数值比较. package Exam01; import java.util.Scanner; public ...
- C#当中的多线程_线程基础
前言 最近工作不是很忙,想把买了很久了的<C#多线程编程实战>看完,所以索性把每一章的重点记录一下,方便以后回忆. 第1章 线程基础 1.创建一个线程 using System; usin ...
随机推荐
- springMvc-入参对象
1.修改或者添加对象 2.多添件查询时候也会遇到 springMvc能够根据属性自动的封装pojo的对象并且支持关联的对象:大致的原理是在传入后台的时候把前台的属性和对象封装成json的形式传入后台, ...
- 玩转web之ligerui(一)---ligerGrid又一次指定url
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u012116457/article/details/27109227 请珍惜小编劳动成果.该文章为小 ...
- Ubuntu不支持rpm安装软件解决方法
Ubuntu不支持rpm安装软件解决方法 以前经常使用的是RedHat Linux,习惯使用rpm方法安装软件.最近发现Ubuntu系统居然不支持rpm方法安装软件,提示信息如下: root@root ...
- CentOS 7.1上安装.Net Core
官方网站给出了几条命令: sudo yum install libunwind libicu curl -sSL -o dotnet.tar.gz https://go.microsoft.com/f ...
- HDU 1426 Sudoku Killer(dfs 解数独)
传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1426 Sudoku Killer Time Limit: 2000/1000 MS (Java/Oth ...
- An Algorithm for Surface Encoding and Reconstruction From 3D Point Cloud Data
An Algorithm for Surface Encoding and Reconstruction From 3D Point Cloud Data https://www.youtube.co ...
- ROUND()和TRUNC()函数
ROUND(number[,decimals]) 其中:number 待做截取处理的数值: decimals 指明需保留小数点后面的位数,可选项.需要注意的是,和trunc函数不同,对截取的数字要四舍 ...
- [JSOI2010]Group 部落划分 Group
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 3661 Solved: 1755[Submit][Status][Discuss] Descripti ...
- ABAP术语-Event
Event 原文:http://www.cnblogs.com/qiangsheng/archive/2008/01/31/1059588.html Occurrence of a change of ...
- ABAP术语-Business Object Type
Business Object Type 原文:http://www.cnblogs.com/qiangsheng/archive/2008/01/10/1033480.html Generic de ...