线程系列07,使用lock语句块或Interlocked类型方法保证自增变量的数据同步
假设多个线程共享一个静态变量,如果让每个线程都执行相同的方法每次让静态变量自增1,这样的做法线程安全吗?能保证自增变量数据同步吗?本篇体验使用lock语句块和Interlocked类型方法保证自增变量的数据同步。
□ 线程不安全、数据不同步的做法
class Program{static int sum = 0;static void Main(string[] args){Stopwatch watch = new Stopwatch();watch.Start();Parallel.For(0, Environment.ProcessorCount, i =>{for (int j = 0; j < 100000000; ++j){AddOne();}});watch.Stop();Console.WriteLine("sum={0},用了{1}", sum, watch.Elapsed);Console.ReadKey();}static void AddOne(){sum++;}}
○ 变量sum是静态的,供所有线程共享
○ Parallel.For提供并行循环, Environment.ProcessorCount表示处理器的处理,如果有4个CPU,就做4组循环
我们发现,结果不是我们期望的400000000,也就是说,在这种情况下的静态变量自增不是线程安全的,换句话说,无法保证共享数据的同步。
□ 通过lock语句块保持数据同步
class Program{static int sum = 0;private static readonly object o = new object();static void Main(string[] args){Stopwatch watch = new Stopwatch();watch.Start();Parallel.For(0, Environment.ProcessorCount, i =>{for (int j = 0; j < 100000000; ++j){AddOne();}});watch.Stop();Console.WriteLine("sum={0},用了{1}", sum, watch.Elapsed);Console.ReadKey();}static void AddOne(){lock (o){sum++;}}}
这一次,使用lock语句块得到了预期的结果。
□ 使用Interlocked保持数据同步
对于int或long类型变量的自增,并且保证类型安全,可以使用Interlocked类。提供的方法包括:
○ int Interlocked.Increment(ref int location),自增1
○ long Interlocked.Increment(ref long location),自增1
○ int Interlocked.Decrement(ref int location),自减1
○ long Interlocked.Decrement(ref long location),自减1
○ int Interlocked.Add(ref int location, int value),自增一个值
○ long Interlocked.Add(ref long location, long value),自增一个值
class Program{static int sum = 0;static void Main(string[] args){Stopwatch watch = new Stopwatch();watch.Start();Parallel.For(0, Environment.ProcessorCount, i =>{for (int j = 0; j < 100000000; ++j){AddOne();}});watch.Stop();Console.WriteLine("sum={0},用了{1}", sum, watch.Elapsed);Console.ReadKey();}static void AddOne(){Interlocked.Increment(ref sum);}}
使用Interlocked也能保证线程安全、数据同步,但耗时较长。
总结:
○ lock语句块和Interlocked类型方法都能保证自增变量的线程安全、数据同步
○ Interlocked类型方法只适用于int,long类型变量,有一定的局限性
线程系列包括:
线程系列01,前台线程,后台线程,线程同步
线程系列02,多个线程同时处理一个耗时较长的任务以节省时间
线程系列03,多线程共享数据,多线程不共享数据
线程系列04,传递数据给线程,线程命名,线程异常处理,线程池
线程系列05,手动结束线程
线程系列06,通过CLR代码查看线程池及其线程
线程系列07,使用lock语句块或Interlocked类型方法保证自增变量的数据同步
线程系列08,实现线程锁的各种方式,使用lock,Montor,Mutex,Semaphore以及线程死锁
线程系列10,无需显式调用线程的情形
线程系列07,使用lock语句块或Interlocked类型方法保证自增变量的数据同步的更多相关文章
- 线程系列08,实现线程锁的各种方式,使用lock,Montor,Mutex,Semaphore以及线程死锁
当涉及到多线程共享数据,需要数据同步的时候,就可以考虑使用线程锁了.本篇体验线程锁的各种用法以及线程死锁.主要包括: ※ 使用lock处理数据同步※ 使用Monitor.Enter和Monitor.E ...
- 线程系列06,通过CLR代码查看线程池及其线程
在"线程系列04,传递数据给线程,线程命名,线程异常处理,线程池"中,我们已经知道,每个进程都有一个线程池.可以通过TPL,ThreadPool.QueueUserWorkItem ...
- C# lock关键词/lock语句块、线程锁
一.lock关键词说明 1. lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁. 2. lock 语句块锁定,功能等同于 Monitor.Enter(obj): ...
- lock语句的递归问题
原文地址 前几天在网上闲逛,无意中看到有这么一道题及其答案,如下: 根据线程安全的相关知识,分析以下代码,当调用test方法时i>10时是否会引起死锁?并简要说明理由. ) { i--; tes ...
- C#线程系列讲座(5):同步技术之Monitor
在上一讲介绍了使用lock来实现线程之间的同步.实际上,这个lock是C#的一个障眼法,在C#编译器编译lock语句时,将其编译成了调用Monitor类.先看看下面的C#源代码: public sta ...
- 左右 Java 于 finally 深度分析语句块
首先,让我们来问你一个问题:finally 声明块将运行? 很多人认为 finally 语句块是一定要运行.其中还包括了一些非常有经验的 Java 程序猿.不幸的是,没有像很多像人们想象,对于这个问题 ...
- finally语句块
finally语句块是搭配着try语句块出现的,也就说必须有try语句块才会有finally语句块,但是并不是try语句块都会搭配有finally语句块出现,我们常见的更多是try...catch.. ...
- synchronized(1)用法简介:修饰方法,修饰语句块
注意: 同一个对象或方法在不同线程中才出现同步问题,不同对象在不同线程互相不干扰. synchronized方法有2种用法:修饰方法,修饰语句块 1.synchronized方法 是某个对象实例内,s ...
- Try-Catch-Finally语句块执行问题
Try-Catch-Finally语句块执行问题 记录一个今天某公司的面试问题,其实我问题回答对了,但是面试官问我动手验证过没有,这还真没有,纯理论,被怼惨了,希望自己能变得更强大. Try-Catc ...
随机推荐
- AdvStringGrid 获取值
stringGrid.row stringgrid.col分别为当前行和列 stringGrid.cells[stringgrid.col,stringGrid.row]就是当前cell的值 ---- ...
- new[] 到底做了什么?
#include<iostream> #include<cstdlib> using std::cout; using std::endl; using std::hex; c ...
- GreenPlum学习笔记:新手入门命令
1.命令行登录数据库 psql -h 192.168.111.111 -U username -d dbname 其中,username为数据库用户名,dbname为数据库名,执行后提示输入密码.(可 ...
- Linux学习笔记:644、755、777权限详解
一.问题 1.在Linux或者Android系统下用命令ll或者ls -la的时候会看到前面-rw-rw-r--一串字符,不知道代表什么? 2.新建vi一个文件之后,经常需要chmod 755 fil ...
- mybatis中多条件判断---choose when的用法
<select id="getFunctionByPage" resultMap="FunctionRlt"> SELECT K.FUNCTION_ ...
- C#连接SQL Server数据库小贴士
在较低版本vs中需要添加using system.data.sqlClient; 在新版本vs中需要写成using System.Data.SqlClient; 作者:耑新新,发布于 博客园 转载请 ...
- AOP实战(1)
AOP在MVC中有广泛的应用 如:IActionFilter. IAuthenticationFilter. IAuthorizationFilter.IExceptionFilter.IResult ...
- Educational Codeforces Round 9 D - Longest Subsequence
D - Longest Subsequence 思路:枚举lcm, 每个lcm的答案只能由他的因子获得,类似素数筛搞一下. #include<bits/stdc++.h> #define ...
- (转)看懂UML类图
转自:http://design-patterns.readthedocs.io/zh_CN/latest/read_uml.html 这里不会将UML的各种元素都提到,我只想讲讲类图中各个类之间的关 ...
- Ionic实战九:ionic视频播放
本模板和以前的方式不同,采用的是 iframe方式引入的视频,如下代码: