【C#】为什么有可能会被多个线程修改的对象要加线程锁
例1、不用线程锁的情况下,两个线程对同一个变量进行加减操作
static void Main(string[] args)
{
Counter counter = new Counter();
var t1 = new Thread(() => TestCounter(counter));
var t2 = new Thread(() => TestCounter(counter));
t1.Start();
t2.Start(); Thread.Sleep(TimeSpan.FromSeconds());//睡眠3秒,保证t1、t2两个线程都运行完毕
Console.WriteLine(counter.count);
Console.Read();
}

对count变量不断地加1减1,最后count应该为0,但可以看出用两个线程来进行这个操作的时候,往往得到的结果并不是0,出现错误。
例2、使用线程锁,两个线程对同一个变量进行加减操作
static void Main(string[] args)
{
CounterWithLock counterlock = new CounterWithLock();
var t1 = new Thread(() => TestCounter(counterlock));
var t2 = new Thread(() => TestCounter(counterlock));
t1.Start();
t2.Start(); Thread.Sleep(TimeSpan.FromSeconds());//睡眠3秒,保证t1、t2两个线程都运行完毕
Console.WriteLine(counterlock.count);
Console.Read();
}

加上线程锁后,结果正常,因此加上线程锁才能保证不会出错。
例1、例2所用到的类和方法
/// <summary>
/// 对同一个变量进行1000次加减操作
/// </summary>
/// <param name="c"></param>
static void TestCounter(CounterBase c)
{
Console.WriteLine("TestCounter start");
for (int i = ; i < ; i++)
{
c.Increment();
c.Decrement();
}
Console.WriteLine("TestCounter end");
}
abstract class CounterBase
{
public abstract void Increment();
public abstract void Decrement();
} /// <summary>
/// 没有锁
/// </summary>
class Counter : CounterBase
{
public int count { get; private set; } public override void Increment()
{
count ++;
} public override void Decrement()
{
count --;
}
} /// <summary>
/// 加锁
/// </summary>
class CounterWithLock : CounterBase
{
private readonly object locker = new object();
public int count { get; private set; } public override void Increment()
{
lock (locker)
{
count++;
}
} public override void Decrement()
{
lock (locker)
{
count--;
}
}
}
【C#】为什么有可能会被多个线程修改的对象要加线程锁的更多相关文章
- WPF非UI线程中调用App.Current.MainWindow.Dispatcher提示其他线程拥有此对象,无权使用。
大家都知道在WPF中对非UI线程中要处理对UI有关的对象进行操作,一般需要使用委托的方式,代码基本就是下面的写法 App.Current.MainWindow.Dispatcher.Invoke(ne ...
- Python之路-python(paramiko,进程和线程的区别,GIL全局解释器锁,线程)
一.paramiko 二.进程.与线程区别 三.python GIL全局解释器锁 四.线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生 ...
- 浅谈线程池(上):线程池的作用及CLR线程池
原文地址:http://blog.zhaojie.me/2009/07/thread-pool-1-the-goal-and-the-clr-thread-pool.html 线程池是一个重要的概念. ...
- 线程间操作无效: 从不是创建控件“”的线程访问它~~~的解决方法~ 线程间操作无效: 从不是创建控件“Control Name'”的线程访问它问题的解决方案及原理分析
看两个例子,一个是在一个进程里设置另外一个进程中控件的属性.另外一个是在一个进程里获取另外一个进程中控件的属性. 第一个例子 最近,在做一个使用线程控制下载文件的小程序(使用进度条控件显示下载进度)时 ...
- C#中的线程(上)-入门 分类: C# 线程 2015-03-09 10:56 53人阅读 评论(0) 收藏
1. 概述与概念 C#支持通过多线程并行地执行代码,一个线程有它独立的执行路径,能够与其它的线程同时地运行.一个C#程序开始于一个单线程,这个单线程是被CLR和操作系统(也称为"主线 ...
- WPF异常“调用线程无法访问此对象,因为另一个线程拥有该对象 ”
WPF中在对界面进行操作的时候,可能会遇到"调用线程无法访问此对象,因为另一个线程拥有该对象"异常,这是因为WPF中只有UI线程才能操作UI元素,非UI线程要访问UI时就会报异常了 ...
- Qt多线程编程总结(一)(所有GUI对象都是线程不安全的)
Qt对线程提供了支持,基本形式有独立于平台的线程类.线程安全方式的事件传递和一个全局Qt库互斥量允许你可以从不同的线程调用Qt方法. 这个文档是提供给那些对多线程编程有丰富的知识和经验的听众的.推荐阅 ...
- Java并发编程实践读书笔记(1)线程安全性和对象的共享
2.线程的安全性 2.1什么是线程安全 在多个线程访问的时候,程序还能"正确",那就是线程安全的. 无状态(可以理解为没有字段的类)的对象一定是线程安全的. 2.2 原子性 典型的 ...
- [JCIP笔记] (三)如何设计一个线程安全的对象
在当我们谈论线程安全时,我们在谈论什么中,我们讨论了怎样通过Java的synchronize机制去避免几个线程同时访问一个变量时发生问题.忧国忧民的Brian Goetz大神在多年的开发过程中,也悟到 ...
随机推荐
- Struts错误信息回传
<td height="20" align="center" class="loginMiddleDiv_loginInfo_window_wa ...
- Your Firefox profile cannot be loaded. It may be missing or inaccessible
ubuntu下出现打开frefox出现Your Firefox profile cannot be loaded. It may be missing or inaccessible 1:用命令行输入 ...
- 前端模块化开发的规范:AMD与CDM
AMD, 异步模块定义. CMD,通用模块规范.
- bzoj4149: [AMPPZ2014]Global Warming
头都烂了怎么头疼啊 考虑先做出对于一个位置以它作为唯一最小值的最远区间,这个可以单调栈上二分搞出来 那么对于一个位置这个区间而言,一定是选择这个区间的最大数是作为最终的唯一最大数最优的 为什么呢?我们 ...
- 简单的JDBC编程步骤
1.加载数据库驱动(com.mysql.jdbc.Driver) 2.创建并获取数据库链接(Connection) 3.创建jdbc statement对象(PreparedStatement) 4. ...
- Python安装pip3常见问题
安装pip3 1.安装 zlib组件: 安装完成后,执行命令 python3 -m pip install redis,报错: RuntimeError: Compression requires t ...
- 使用pngcrush压缩png图片
写在前面: Pngcrush是一个优化的PNG(便携式网络图形)文件.它可以运行在MSDOS窗口中一个命令行,或从UNIX或LINUX命令行.其主要目的是为了 减少PNG IDAT数据 ...
- BZOJ_4327_JSOI2012 玄武密码_AC自动机
BZOJ_4327_JSOI2012 玄武密码_AC自动机 Description 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便 ...
- python整数与IP地址转换 [转]
我们有时会将一个整数与IP地址进行互换,用python代码实现很简单将一个整数如2000000,变为一个IP地址的方式 >>> import socket >>> ...
- Centos添加jdk环境变量
假设将jdk解压到/opt/jdk1.8.0_131. echo "export JAVA_HOME=/opt/jdk1.8.0_131" >> /etc/profil ...