线程资料整理

如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。 
  或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。 
  线程安全问题都是由全局变量及静态变量引起的。 
  若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时对一个变量执行读写操作,一般都需要考虑线程同步,否则就可能影响线程安全。

lock的目的是防止多线程执行的时候出现并发操作问题,加上lock的引用类型的对象,在其锁定的区域内,在一个时刻只允许一个线程操作。

lock只能锁定一个引用类型变量,也就是锁定一个地址

class Program

    {
        static void Main(string[] args)
        {
        threda t=new threda();
        threda.obj.i = 10;
        Thread th1 = new Thread(new ThreadStart(t.hhh));
        th1.Name = "th1";
        th1.Start();

        Thread th2 = new Thread(new ThreadStart(t.hhh));
        th2.Name = "th2";
        th2.Start();
        }

    }

class threda
    {
        public static sss obj = new sss();

        public void hhh()
        {
            lock (obj)
            {
                for (int i = 0; i < 7; i++)
                {
                    Thread.Sleep(500);

                    if (obj.i >0)
                    {
                        obj.i--;
                        Console.WriteLine("当前线程名:"+Thread.CurrentThread.Name+", obj.i= " + obj.i);
                    }
                }
            }
        }

    }

    class sss
    {
       public int i ;
    }

加锁和不加锁运行的结果有区别 :

加锁后:i的值会一个个递减,不会出现跳跃,不会出现重复输出,一直到0值;

不加锁:i的值输出会出现跳跃,不连续递减,可能还会出现-1值输出;

原因:加锁后,一个时刻只能有一个线程执行被锁区域的代码,两个线程都是有先后顺序执行的,所以不会出现间断输出。

C# 理解lock

一. 为什么要lock,lock了什么?

当我们使用线程的时候,效率最高的方式当然是异步,即各个线程同时运行,其间不相互依赖和等待。但当不同的线程都需要访问某个资源的时候,就需要同步机制了,也就是说当对同一个资源进行读写的时候,我们要使该资源在同一时刻只能被一个线程操作,以确保每个操作都是有效即时的,也即保证其操作的原子性。lock是C#中最常用的同步方式,格式为lock(objectA){codeB} 。

lock(objectA){codeB} 看似简单,实际上有三个意思,这对于适当地使用它至关重要:
1. objectA被lock了吗?没有则由我来lock,否则一直等待,直至objectA被释放。
2. lock以后在执行codeB的期间其他线程不能调用codeB,也不能使用objectA。
3. 执行完codeB之后释放objectA,并且codeB可以被其他线程访问。

二. lock(this)怎么了?

我们看一个例子:

using System;
using System.Threading;
namespace Namespace1
{
    class C1
    {
        private bool deadlocked = true;
        //这个方法用到了lock,我们希望lock的代码在同一时刻只能由一个线程访问
        public void LockMe(object o)
        {
            lock (this)
            {
                while(deadlocked)
                {
                    deadlocked = (bool)o;
                    Console.WriteLine("Foo: I am locked :(");
                    Thread.Sleep(500);
                }
            }
        }
        //所有线程都可以同时访问的方法
        public void DoNotLockMe()
        {
            Console.WriteLine("I am not locked :)");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            C1 c1 = new C1();
            //在t1线程中调用LockMe,并将deadlock设为true(将出现死锁)
            Thread t1 = new Thread(c1.LockMe);
            t1.Start(true);
            Thread.Sleep(100);
            //在主线程中lock c1
            lock (c1)
            {
                //调用没有被lock的方法
                c1.DoNotLockMe();
                //调用被lock的方法,并试图将deadlock解除
                c1.LockMe(false);
            }
        }
    }

复制代码

在t1线程中,LockMe调用了lock(this), 也就是Main函数中的c1,这时候在主线程中调用lock(c1)时,必须要等待t1中的lock块执行完毕之后才能访问c1,即所有c1相关的操作都无法完成,于是我们看到连c1.DoNotLockMe()都没有执行。

把C1的代码稍作改动:

class C1
    {
        private bool deadlocked = true;
        private object locker = new object();
        //这个方法用到了lock,我们希望lock的代码在同一时刻只能由一个线程访问
        public void LockMe(object o)
        {
            lock (locker)
            {
                while(deadlocked)
                {
                    deadlocked = (bool)o;
                    Console.WriteLine("Foo: I am locked :(");
                    Thread.Sleep(500);
                }
            }
        }
        //所有线程都可以同时访问的方法
        public void DoNotLockMe()
        {
            Console.WriteLine("I am not locked :)");
        }
    }

复制代码

这次我们使用一个私有成员作为锁定变量(locker),在LockMe中仅仅锁定这个私有locker,而不是整个对象。这时候重新运行程序,可以看到虽然t1出现了死锁,DoNotLockMe()仍然可以由主线程访问;LockMe()依然不能访问,原因是其中锁定的locker还没有被t1释放。

关键点:
1. lock(this)的缺点就是在一个线程(例如本例的t1)通过执行该类的某个使用"lock(this)"的方法(例如本例的LockMe())锁定某对象之后, 导致整个对象无法被其他线程(例如本例的主线程)访问 - 因为很多人在其他线程(例如本例的主线程)中使用该类的时候会使用类似lock(c1)的代码。
2. 锁定的不仅仅是lock段里的代码,锁本身也是线程安全的。
3. 我们应该使用不影响其他操作的私有对象作为locker。
4. 在使用lock的时候,被lock的对象(locker)一定要是引用类型的,如果是值类型,将导致每次lock的时候都会将该对象装箱为一个新的引用对象(事实上如果使用值类型,C#编译器(3.5.30729.1)在编译时就会给出一个错误)。

--该资料来源于网络.

时间: 2024-10-12 19:29:58

线程资料整理的相关文章

不错的Nodejs或者JS资料整理

资料整理 Node.js官网 - 可以下载到Node.js以及查看官方文档 Node.js教程 - 菜鸟教程网 Javascript模块化编程(一):模块的写法 - 阮一峰老师的日志,很值得看 CommonJS官网 requireJS官网 - AMD规范在其中 seaJS官网 - CMD规范在其中 request模块 cheerio模块

iOS开发资料整理

Please help me contribute to this list, for non-experience iOS developers or someone who need a come-in-handy library list to refer or to use in their projects. Fork, edit and send a PR are all things you can do! Table of Contents UI Component// UI组件

iOS 开发学习资料整理(持续更新)

"如果说我看得比别人远些,那是因为我站在巨人们的肩膀上." ---牛顿 iOS及Mac开源项目和学习资料[超级全面] http://www.kancloud.cn/digest/ios-mac-study/84557 iOS 学习资料整理 https://segmentfault.com/a/1190000002473595#articleHeader16 iOS.mac开源项目及库 https://github.com/Tim9Liu9/TimLiu-iOS Swift语言 http

mql4资料整理

mql4资料整理 开发工具和SDK相关 http://codebase.mql4.com/cn/在该页面的左边有MeteTrader 5 和 页面 MT4的开发工具下载 开发资料1. 参考文档http://docs.mql4.com/cn/ 2.其它相关bloghttp://www.cnblogs.com/niniwzw/category/212678.htmlhttp://www.cnblogs.com/niniwzw/tag/MQL4/3.其它相关资源学习列表http://search.do

Doxygen资料整理

@author          作者@brief             摘要@version         版本号@date             日期@file                文件名,可以默认为空,DoxyGen会自己加@class             类名@param           函数参数@return           函数返回值描述@exception      函数抛异常描述@warning         函数使用中需要注意的地方@remarks

zz 圣诞丨太阁所有的免费算法视频资料整理

首发于 太阁实验室 关注专栏 写文章 圣诞丨太阁所有的免费算法视频资料整理 Ray Cao· 12 小时前 感谢大家一年以来对太阁实验室的支持,我们特地整理了在过去一年中我们所有的原创算法类视频,均为免费观看,方便大家学习. 先放一个ACM大神讲解的算法题视频(国外传优酷真的是太不容易了……). ACM大神精讲北美最新面试题—在线播放—优酷网,视频高清在线观看http://v.youku.com/v_show/id_XMTg2ODk0MzIwMA==.html 其余视频: [公开课]ACM大神精

JS搞基指南----延迟对象入门提高资料整理

原文:JS搞基指南----延迟对象入门提高资料整理 JavaScript的Deferred是比较高大上的东西,  主要的应用还是主ajax的应用,  因为JS和nodeJS这几年的普及,  前端的代码越来越多,  各种回调套回调再套回调实在太让人崩溃, 所以就从后端拖了一个延迟对象这货, 用来解决回调地狱这个问题 .  我们使用ajax的时候多数都是为ajax添加回调 ,然后异步向服务器发送请求, 比如如下原生的XHR代码: <!DOCTYPE html PUBLIC "-//W3C//D

archlinux相关资料整理

Arch linux Arch Linux Wiki Arch linux Wiki Markdown Arch Wiki python continuing ... archlinux相关资料整理,布布扣,bubuko.com

3分钟带你了解PowerShell发展历程——PowerShell各版本资料整理

本文带你了解PowerShell发展历程,顺便整理了一点资料,方便大家查询. Windows PowerShell? 是基于任务的命令行管理程序和脚本语言,专为进行系统管理而设计. 在 .NET Framework 的基础上构建的 Windows PowerShell 可帮助 IT 专业人士和高级用户控制和自动执行 Windows 操作系统以及在 Windows 上运行的应用程序的管理. UNIX 系统一直有着功能强大的脚本(shell),Windows PowerShell 的诞生就是要提供功