C#线程安全使用(三)
在讲CancellationTokenSource之前我决定先讲一下lock和Interlocked,如果能很好的理解这两个,再去理解CancellationTokenSource就会方便很多,由于我也是后起使用多线程,使用的时候就是直接运用FramWork4的东西,这样导致了很多东西学起来很吃力,当回顾了以前的知识点后,发现新出的东西如此好理解。
先看一下Lock的使用,下面是一个例子。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace LockConsole
{
class Program
{
static object lockint = ;
static void Main()
{
Task[] tlist=new Task[]; Thread[] threads = new Thread[]; for (int i = ; i < ; i++)
{
var action = new Action<object>(Withdraw);
Task t = new Task(action, i);
tlist[i] = t;
//Thread t = new Thread(new ThreadStart(acc.DoTransactions));
//threads[i] = t;
}
for (int i = ; i < ; i++)
{
tlist[i].Start(); //threads[i].Start();
}
Console.Read();
} static void Withdraw(object i)
{
int amount = int.Parse(i.ToString());
int balance = ; lock (lockint)//删除lock就会造成 线程混乱
{
if (balance >= amount)
{
Console.WriteLine("当前线程{0},当前状态{1}", Thread.CurrentThread.GetHashCode(), Thread.CurrentThread.ThreadState + "Balance before Withdrawal : " + balance);
Console.WriteLine("当前线程{0},当前状态{1}", Thread.CurrentThread.GetHashCode(), Thread.CurrentThread.ThreadState + "Amount to Withdraw : -" + amount);
balance = balance - amount;
Console.WriteLine("当前线程{0},当前状态{1}", Thread.CurrentThread.GetHashCode(), Thread.CurrentThread.ThreadState + "Balance after Withdrawal : " + balance); } }
} } }
输出结果如下,他的线程都是一个接一个的,线程11后是线程12,然后是13,14,11等。每个线程都是等到执行完了下一个才执行。

在看一下没有Lock的结果,如下图,线程是混乱的,12线程的函数没执行完13就开始了。

有了上面的例子,Lock就很好理解了,他是为了保障资源同一时间只被一个线程使用,虽然该例子中没有使用Lock的资源,但线程还是一个接一个的执行,因为使用了lock线程就会一个接一个执行。
接下来看一下interLock,这是一个MSDN的例子,我觉得不错,他的意思是,把usingResource作为一个锁,当多线程开始运行,函数UseResource()需要判断usingResource的值,当usingResource等于0的时候,当前线程不运行,否则运行,当本线程运行时,要修改usingResource的值为1,这样确保其他线程不运行,即同一时间只运行一个线程。
如果这样需求用到开发中,会出现一个问题,那就是当一个线程改变usingResource的值的一瞬间,别的线程读取了usingResource的值,那这个线程也被运行了。
这时就需要InterLock了。代码如下。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace MyInterlockedExchangeExampleClass
{
class MyInterlockedExchangeExampleClass
{
//0 for false, 1 for true.
private static int usingResource = ; private const int numThreadIterations = ;
private const int numThreads = ; static void Main()
{
Thread myThread;
Random rnd = new Random(); for (int i = ; i < numThreads; i++)
{
myThread = new Thread(new ThreadStart(MyThreadProc));
myThread.Name = String.Format("Thread{0}", i + ); //Wait a random amount of time before starting next thread.
Thread.Sleep(rnd.Next(, ));
myThread.Start();
}
} private static void MyThreadProc()
{
for (int i = ; i < numThreadIterations; i++)
{
UseResource(); //Wait 1 second before next attempt.
Thread.Sleep();
}
} //A simple method that denies reentrancy.
static bool UseResource()
{
//0 indicates that the method is not in use.
//原始值是0,判断是时候使用原始值,但判断后值为1,进行了设置
if ( == Interlocked.Exchange(ref usingResource, ))
{
Console.WriteLine("{0} acquired the lock", Thread.CurrentThread.Name); //Code to access a resource that is not thread safe would go here. //Simulate some work
Thread.Sleep(); Console.WriteLine("{0} exiting lock", Thread.CurrentThread.Name); //Release the lock
Interlocked.Exchange(ref usingResource, );
return true;
}
else
{
Console.WriteLine(" {0} was denied the lock", Thread.CurrentThread.Name);
return false;
}
} } }
理解了lock和interlock后下一章讲解CancellationTokenSource。
----------------------------------------------------------------------------------------------------
注:此文章为原创,任何形式的转载都请联系作者获得授权并注明出处!
若您觉得这篇文章还不错,请点击下方的【推荐】,非常感谢!

C#线程安全使用(三)的更多相关文章
- java核心知识点学习----创建线程的第三种方式Callable和Future CompletionService
前面已经指出通过实现Runnable时,Thread类的作用就是将run()方法包装成线程执行体,那么是否可以直接把任意方法都包装成线程执行体呢?Java目前不行,但其模仿者C#中是可以的. Call ...
- Android线程管理(三)——Thread类的内部原理、休眠及唤醒
线程通信.ActivityThread及Thread类是理解Android线程管理的关键. 线程,作为CPU调度资源的基本单位,在Android等针对嵌入式设备的操作系统中,有着非常重要和基础的作用. ...
- Windbg 进程与线程 《第三篇》
Windbg既可以显示进程和线程列表,又可以显示指定进程或线程的详细信息.调试命令可以提供比taskmgr更详尽的进程资料,在调试过程中不可或缺. 一.进程命令 进程命令包括这些内容:显示进程列表.进 ...
- IOS 多线程,线程同步的三种方式
本文主要是讲述 IOS 多线程,线程同步的三种方式,更多IOS技术知识,请登陆疯狂软件教育官网. 一般情况下我们使用线程,在多个线程共同访问同一块资源.为保护线程资源的安全和线程访问的正确性. 在IO ...
- 7. Callable 创建线程的方式三
package com.gf.demo06; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionEx ...
- 正确停止线程的方式三 使用Thread类中的内置的中断标记位-----------不熟悉
package charpter10; public class Processor implements Runnable { @Override public void run() { for ( ...
- 编写一个程序,开启 3 个线程,这三个线程的 ID 分别为 A、B、C,每个线程将自己的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示。如:ABCABCABC…… 依次递归
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.uti ...
- Android线程管理(三)——Thread类的内部原理、休眠及唤醒
线程通信.ActivityThread及Thread类是理解Android线程管理的关键. 线程,作为CPU调度资源的基本单位,在Android等针对嵌入式设备的操作系统中,有着非常重要和基础的作用. ...
- java核心知识点----创建线程的第三种方式 Callable 和 Future CompletionService
前面已经指出通过实现Runnable时,Thread类的作用就是将run()方法包装成线程执行体,那么是否可以直接把任意方法都包装成线程执行体呢?Java目前不行,但其模仿者C#中是可以的. Call ...
- Java之创建线程的方式三:实现Callable接口
import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util ...
随机推荐
- 字符串转义为HTML
有时候后台返回的数据中有字符串,并需要将字符串转化为HTML,下面封装了一个方法,如下 // html转义 function htmlspecialchars_decode(string, quote ...
- SpringBoot报错:Failed to load ApplicationContext(Mapped Statements collection already contains value)
错误提示: Caused by: java.lang.IllegalArgumentException: Mapped Statements collection already contains v ...
- vue 源码学习三 vue中如何生成虚拟DOM
vm._render 生成虚拟dom 我们知道在挂载过程中, $mount 会调用 vm._update和vm._render 方法,vm._updata是负责把VNode渲染成真正的DOM,vm._ ...
- 《SpringMVC从入门到放肆》十四、SpringMVC分组数据校验
上一篇我们学习了数据校验,但是在实际项目中,还是有些不够灵活,今天我们就来继续学习一种更灵活的数据校验方法——分组数据校验. 一.什么是分组校验 校验规则是定义在实体中的,而同一个实体可以被多个Con ...
- node.js 递归复制文件夹(附带文件过滤功能)
1.简介: 很简单,写了一个node操作文件的小脚本,主要实现对目标文件夹中内容的复制.还顺带一个按照文件夹或者文件名过滤的功能. 2.应用场景 适合基于 node 环境的项目,项目打包的时候,配合 ...
- linux操作命令之搜索命令
1.文件搜索命令:locate 文件名 在后台数据库中按照文件名搜索,搜素速度更快 /var/lib/mlocate:#locate命令所搜索的后台数据库 updatedb:更新数据库 updated ...
- MySQL数据备份方法
MySQL的备份和还原 备份:副本 RAID1,RAID10:保证硬件损坏而不会业务中止: DROP TABLE mydb.tb1; 备份类型: 热备份.温备份和冷备 ...
- i春秋官网4.0上线啦 文末有福利
爱瑞宝地(Everybody)期待了很久的 i春秋官网4.0上线啦 除了产品的功能更加完善 性能和体验也将大幅度提高 清新.舒适的视觉感受 搭配更加便捷的操作流程 只需一秒,扫码立即登录 即刻进入网络 ...
- ansible基础-加密
一 简介 注:本文demo使用ansible2.7稳定版 众所周知,ansible是很火的一个自动化部署工具,在ansible控制节点内,存放着当前环境服务的所有服务的配置信息,其中自然也包括一些敏感 ...
- Python档案袋( 进程与协程 )
Python的进程和线程是使用的操作系统的原生线程和进程,其是去调用操作系统的相应接口实现 进程:之间不可直接共享数据,是资源的集合,进程必须有一个线程 线程:基于进程,之间可直接共享数据,可执行,只 ...