线程基础三 使用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 ...
随机推荐
- 从零搭建docker+jenkins 自动化部署环境
从零搭建docker+jenkins+node.js自动化部署环境 本次案例基于CentOS 7系统 适合有一定docker使用经验的人阅读 适合有一定linux命令使用经验的人阅读 1.docker ...
- python接口测试-项目实践(六) 实际结果与预期结果对比之 数据源与数据库对比
六 与数据库对比 import pymssql def compare_expected_vs_db(): diff_list = [] # 存储不一致的代码 with pymssql.connect ...
- PHP使用memcache长连接作为RPC客户端需要注意的地方
memcache扩展版本 3.0.8 一. retry_interval $retry_interval 某个rpc服务器端失败后故障转移的时间,retry_interval的时间内,该节点会被一直标 ...
- NO.006-2018.02.11《卜算子·我住长江头》宋代:李之仪
卜算子·我住长江头_古诗文网(bǔ) 卜算子·我住长江头 宋代:李之仪 我住长江头,君住长江尾.日日思君不见君,共饮长江水. 我居住在长江上游,你居住在长江下游. 天天想念你却见不到你,共同喝着长江的 ...
- Eclipse Java常用快捷键(Eclipse Shortcut Keys for Java Top10)(转)
Eclipse Java常用快捷键(Eclipse Shortcut Keys for Java Top10) 0.背景Eclipse作为Java的OpenSource开发IDE,已经是开发人员进行J ...
- springboot(服务端接口)获取URL请求参数的几种方法
原文地址:http://www.cnblogs.com/xiaoxi/p/5695783.html 一.下面为7种服务端获取前端传过来的参数的方法 常用的方法为:@RequestParam和@Req ...
- [18/11/28]Java中的包(package)
一.为何引入包? 包机制是Java中管理类的重要手段. 开发中,我们会遇到大量同名的类,通过包我们很容易对解决类重名的问题,也可以实现对类的有效管理. 包对于类,相当于文件夹对于文件的作用.(同一文件 ...
- 用HTML写伪类选择器,结构伪类选择器,伪元素选择器样式
html,css lorem乱序铭文 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nesciunt, nihil? Lorem ...
- HTML中id和class选择器
<1>.id和class的区别? id相当于人的身份证不可以重复 class相当于人的名称可以重复 一个HTML标签只能绑定一个id名称 一个HTML标签可以绑定多个class名称 < ...
- linux 中$ 意思
grep -n sh$ text.txt 查找文件内容中以 Sh 结尾. grep -n ^a text.txt 文件文件内容中以 a 开头. grep -n ^$ text.txt ...