博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
并行开发-线程同步机制
阅读量:7055 次
发布时间:2019-06-28

本文共 3165 字,大约阅读时间需要 10 分钟。

线程同步技术

争用条件:

如果两个或多个线程访问相同的对象,并且对共享状态的访问没有同步,就会出现争用条件

class StateObject    {        private int state = 5;        public void ChangeState()        {            state++;            if (state == 5)            {                Console.WriteLine("value=5"); } state = 5; } }
class ThreadTest    {        static void Main(string[] args)        {            StateObject m = new StateObject();            Thread t1 = new Thread(ChangeState);                       t1.Start(m);                       Console.ReadKey();        }        static void ChangeState(object o)        {            StateObject m = o as StateObject; while (true) { m.ChangeState(); } } }

此时运行程序是没有输出的,因为StateObject类中state初始值是5,if条件不会进入,随后又将state从新初始化为5

两个线程执行

static void Main(string[] args)        {            StateObject m = new StateObject();            Thread t1 = new Thread(ChangeState);            Thread t2 = new Thread(ChangeState);            t1.Start(m);            t2.Start(m);            Console.ReadKey();        }

此时会不停的打印"value=5",原因在于:一个线程在判断语句处时,另一个线程可能又将state的值改为了5,而导致输出合法

死锁

class Deadlock{    static StateObject o1 = new StateObject();    static StateObject o2 = new StateObject();    public static void DeadlockA(object o)    {        lock (o1)        {            Console.WriteLine("我是线程{0},我锁定了对象o1", o);            lock (o2)            {                Console.WriteLine("我是线程{0},我锁定了对象o2", o);            }        }    }    public static void DeadlockB(object o)    {        lock (o2)        {            Console.WriteLine("我是线程{0},我锁定了对象o2", o);            lock (o1)            {                Console.WriteLine("我是线程{0},我锁定了对象o1", o);            }        }    }}
Thread t1 = new Thread(Deadlock.DeadlockA); Thread t2 = new Thread(Deadlock.DeadlockB);        t1.Start("t1");        t2.Start("t2");

t1线程执行DeadlockA()方法顺序锁定o1和o2,t2线程执行DeadlockB()方法顺序锁定o2和o1,当前结果显示t1线程锁定了o1后,t2线程在t1线程锁定o1后抢占进来,锁定了o2,t2在等t1解锁,t1在等t2解锁,都处于挂起状态在等对方解锁,这就形成了死锁,线程将无限等待下去

这个问题应该从一开始就设计好锁定顺序,也可以为锁定义超时时间来处理,保证“上锁”这个操作在一个线程上执行也是避免死锁的方法之一

C#中有多个用于多线程的同步技术

  • lock语句
  • Interlocked类
  • Monitor类
  • SpinLock类
  • WaitHandle类
  • Mutex类
  • Semapphore类
  • Event类
  • Barrier类
  • ReaderWriteLockSlim类

其中lock语句/Interlocked类/Monitor类可用于进程内存的同步,其它几个提供了多进程之间的线程同步

Lock

C#使用lock语句锁定在线程中共享的变量,如果一个线程锁定了变量,另一个线程就必须等待该锁定的解除

static void ChangeState(object o)        {            StateObject m = o as StateObject;            while (true)            {
          //给变量m加锁 lock (m) { m.ChangeState(); } } }

因为实例的对象也可以用于外部的同步访问,而且不能在类自身控制这种访问,所以应采用SyncRoot模式,创建私有对象,将这个对象用于lock语句

private static object syncRoot= new object();        static void ChangeState(object o)        {            StateObject m = o as StateObject;            while (true)            {                lock (aync)                {                    m.ChangeState();                }            }        }

需要注意:

1:lock只能锁定对象,即引用类型,不能锁定值类型.

2:lock不能锁定空值,因为null是不需要被释放的

3:不能锁定string类型,虽然它也是引用类型的。因为字符串类型被CLR“暂留”,这意味着整个程序中任何给定字符串都只有一个实例,具有相同内容的字符串上放置了锁,就将锁定应用程序中该字符串的所有实例

4:避免锁定public类型,如果该实例可以被公开访问,则 lock(this) 可能会有问题,因为不受控制的代码也可能会锁定该对象

 

转载于:https://www.cnblogs.com/GnailGnepGnaw/p/10658684.html

你可能感兴趣的文章
.net程序防止反编译
查看>>
第四章 虚拟化 虚拟机迁移
查看>>
基于node.js的sso(单点登录-客户端校验)
查看>>
C++中的几个区域
查看>>
015 jenkins + maven + springboot + git + docker
查看>>
在Ubuntu Server 13.10系统中安装配置OpenSSH
查看>>
我的友情链接
查看>>
关于宿主机与虚拟机网络连接的怪现象
查看>>
mysql集群一:主从复制,通过mysql-proxy做负载均衡
查看>>
mysql 取模分表
查看>>
ubuntu apt-get apt-cache dpkg命令使用
查看>>
percona在ubuntu上的安装
查看>>
find 命令详解
查看>>
采用RESTORE ARCHIVELOG恢复归档
查看>>
华云数据与锐捷网络达成战略合作 聚焦行业云
查看>>
RHEL5.2利用lvm增加linux根分区的容量
查看>>
MDT 2013排错Provider:SQL Network Interfaces,error:26
查看>>
桌面支持--不能显示中文字体,系统已调成中文 而且不能打字
查看>>
古城钟楼微博:葡萄城程序员演练技术的产物
查看>>
最常用的四种数据分析方法
查看>>