在讲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#线程安全使用(三)的更多相关文章

  1. java核心知识点学习----创建线程的第三种方式Callable和Future CompletionService

    前面已经指出通过实现Runnable时,Thread类的作用就是将run()方法包装成线程执行体,那么是否可以直接把任意方法都包装成线程执行体呢?Java目前不行,但其模仿者C#中是可以的. Call ...

  2. Android线程管理(三)——Thread类的内部原理、休眠及唤醒

    线程通信.ActivityThread及Thread类是理解Android线程管理的关键. 线程,作为CPU调度资源的基本单位,在Android等针对嵌入式设备的操作系统中,有着非常重要和基础的作用. ...

  3. Windbg 进程与线程 《第三篇》

    Windbg既可以显示进程和线程列表,又可以显示指定进程或线程的详细信息.调试命令可以提供比taskmgr更详尽的进程资料,在调试过程中不可或缺. 一.进程命令 进程命令包括这些内容:显示进程列表.进 ...

  4. IOS 多线程,线程同步的三种方式

    本文主要是讲述 IOS 多线程,线程同步的三种方式,更多IOS技术知识,请登陆疯狂软件教育官网. 一般情况下我们使用线程,在多个线程共同访问同一块资源.为保护线程资源的安全和线程访问的正确性. 在IO ...

  5. 7. Callable 创建线程的方式三

    package com.gf.demo06; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionEx ...

  6. 正确停止线程的方式三 使用Thread类中的内置的中断标记位-----------不熟悉

    package charpter10; public class Processor implements Runnable { @Override public void run() { for ( ...

  7. 编写一个程序,开启 3 个线程,这三个线程的 ID 分别为 A、B、C,每个线程将自己的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示。如:ABCABCABC…… 依次递归

    import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.uti ...

  8. Android线程管理(三)——Thread类的内部原理、休眠及唤醒

    线程通信.ActivityThread及Thread类是理解Android线程管理的关键. 线程,作为CPU调度资源的基本单位,在Android等针对嵌入式设备的操作系统中,有着非常重要和基础的作用. ...

  9. java核心知识点----创建线程的第三种方式 Callable 和 Future CompletionService

    前面已经指出通过实现Runnable时,Thread类的作用就是将run()方法包装成线程执行体,那么是否可以直接把任意方法都包装成线程执行体呢?Java目前不行,但其模仿者C#中是可以的. Call ...

  10. Java之创建线程的方式三:实现Callable接口

    import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util ...

随机推荐

  1. mysql数据库 ,java 代码巧妙结合提升系统性能。

       查询频繁的表t_yh_transport_task 保证数据量最少,增加查询效率, 常用于查询的字段增加索引, 每日定时移动数据 <!-- 医院系统预约任务历史删除定时器 --> & ...

  2. FCC学习笔记(三)

    Using Objects for Lookups // 定义 phoneticLookupfunction phoneticLookup(val) { var result = "&quo ...

  3. .Net Core 部署 CentOs7+Nginx

    先爆图 由于是初学者,部署出来这个界面也不容易,此前第一步弄了个这个出来 动态的没问题,然后静态资源死活就是不出来,弄了两个小时没有结果,带着遗憾睡了个觉 试验1: server { listen ; ...

  4. Redis sentinel 哨兵模式

    一.sentinel介绍 Sentinel作用: 1):Master状态检测 2):如果Master异常,则会进行Master-Slave切换,将其中一个Slave作为Master,将之前的Maste ...

  5. DOM-节点概念-属性

    1.节点的概念 页面中的所有内容,包括标签,属性,文本(文字,空格,回车,换行等),也就是说页面的所有内容都可以叫做节点. 2.节点相关的属性 2.1.节点分类 **标签节点:**比如 div 标签, ...

  6. php调用第三方接口

    方式一 $url = 'http://ip.taobao.com/service/getIpInfo.php?ip='.$realip;$data = file_get_contents(" ...

  7. 如何在mysql客户端即mysql提示符下执行操作系统命令

    环境描述: mysql版本:5.5.57-log 操作系统版本:Red Hat Enterprise Linux Server release 6.6 (Santiago) 需求描述: 在mysql的 ...

  8. JavaScript 异步编程的前世今生(下)

    ES6 中的 Generator 在 ES6 出现之前,基本都是各式各样类似Promise的解决方案来处理异步操作的代码逻辑,但是 ES6 的Generator却给异步操作又提供了新的思路,马上就有人 ...

  9. Android OpenSL ES 开发:使用 OpenSL 播放 PCM 数据

    OpenSL ES 是基于NDK也就是c语言的底层开发音频的公开API,通过使用它能够做到标准化, 高性能,低响应时间的音频功能实现方法. 这次是使用OpenSL ES来做一个音乐播放器,它能够播放m ...

  10. [Swift]LeetCode223. 矩形面积 | Rectangle Area

    Find the total area covered by two rectilinear rectangles in a 2D plane. Each rectangle is defined b ...