当前位置: 首页 > news >正文

网页设计与网站开发项目东莞软件定制

网页设计与网站开发项目,东莞软件定制,wordpress主题 插件,wordpress百度云下载三.线程的同步和通讯——生产者和消费者假设这样一种情况#xff0c;两个线程同时维护一个队列#xff0c;如果一个线程对队列中添加元素#xff0c;而另外一个线程从队列中取用元素#xff0c;那么我们称添加元素的线程为生产者#xff0c;称取用元素的线程为消费者。…  三.线程的同步和通讯——生产者和消费者 假设这样一种情况两个线程同时维护一个队列如果一个线程对队列中添加元素而另外一个线程从队列中取用元素那么我们称添加元素的线程为生产者称取用元素的线程为消费者。生产者与消费者问题看起来很简单但是却是多线程应用中一个必须解决的问题它涉及到线程之间的同步和通讯问题。 前面说过每个线程都有自己的资源但是代码区是共享的即每个线程都可以执行相同的函数。但是多线程环境下可能带来的问题就是几个线程同时执行一个函数导致数据的混乱产生不可预料的结果因此我们必须避免这种情况的发生。C#提供了一个关键字lock它可以把一段代码定义为互斥段critical section互斥段在一个时刻内只允许一个线程进入执行而其他线程必须等待。在C#中关键字lock定义如下 lock(expression) statement_block expression代表你希望跟踪的对象通常是对象引用。一般地如果你想保护一个类的实例你可以使用this如果你希望保护一个静态变量如互斥代码段在一个静态方法内部一般使用类名就可以了。而statement_block就是互斥段的代码这段代码在一个时刻内只可能被一个线程执行。   下面是一个使用lock关键字的典型例子我将在注释里向大家说明lock关键字的用法和用途 //lock.csusing System;using System.Threading; internal class Account {  int balance;  Random r new Random();  internal Account(int initial)   {  balance initial;  }   internal int Withdraw(int amount)   {  if (balance 0)   {    file://如果balance小于0则抛出异常    throw new Exception(Negative Balance);  }  //下面的代码保证在当前线程修改balance的值完成之前  //不会有其他线程也执行这段代码来修改balance的值  //因此balance的值是不可能小于0的  lock (this)  {    Console.WriteLine(Current Thread:Thread.CurrentThread.Name);    file://如果没有lock关键字的保护那么可能在执行完if的条件判断之后    file://另外一个线程却执行了balancebalance-amount修改了balance的值    file://而这个修改对这个线程是不可见的所以可能导致这时if的条件已经不成立了    file://但是这个线程却继续执行balancebalance-amount所以导致balance可能小于0    if (balance amount)     {    Thread.Sleep(5);    balance balance - amount;    return amount;    }     else     {    return 0; // transaction rejected    }  }  }  internal void DoTransactions()   {  for (int i 0; i 100; i)     Withdraw(r.Next(-50, 100));  }} internal class Test {  static internal Thread[] threads new Thread[10];  public static void Main()   {  Account acc new Account (0);  for (int i 0; i 10; i)   {    Thread t new Thread(new ThreadStart(acc.DoTransactions));    threads[i] t;  }  for (int i 0; i 10; i)     threads[i].Namei.ToString();  for (int i 0; i 10; i)     threads[i].Start();  Console.ReadLine();  }} 而多线程公用一个对象时也会出现和公用代码类似的问题这种问题就不应该使用lock关键字了这里需要用到System.Threading中的一个类Monitor我们可以称之为监视器Monitor提供了使线程共享资源的方案。   Monitor类可以锁定一个对象一个线程只有得到这把锁才可以对该对象进行操作。对象锁机制保证了在可能引起混乱的情况下一个时刻只有一个线程可以访问这个对象。Monitor必须和一个具体的对象相关联但是由于它是一个静态的类所以不能使用它来定义对象而且它的所有方法都是静态的不能使用对象来引用。下面代码说明了使用Monitor锁定一个对象的情形 ......Queue oQueuenew Queue();......Monitor.Enter(oQueue);......//现在oQueue对象只能被当前线程操纵了Monitor.Exit(oQueue);//释放锁 如上所示当一个线程调用Monitor.Enter()方法锁定一个对象时这个对象就归它所有了其它线程想要访问这个对象只有等待它使用Monitor.Exit()方法释放锁。为了保证线程最终都能释放锁你可以把Monitor.Exit()方法写在try-catch-finally结构中的finally代码块里。对于任何一个被Monitor锁定的对象内存中都保存着与它相关的一些信息其一是现在持有锁的线程的引用其二是一个预备队列队列中保存了已经准备好获取锁的线程其三是一个等待队列队列中保存着当前正在等待这个对象状态改变的队列的引用。当拥有对象锁的线程准备释放锁时它使用Monitor.Pulse()方法通知等待队列中的第一个线程于是该线程被转移到预备队列中当对象锁被释放时在预备队列中的线程可以立即获得对象锁。 下面是一个展示如何使用lock关键字和Monitor类来实现线程的同步和通讯的例子也是一个典型的生产者与消费者问题。这个例程中生产者线程和消费者线程是交替进行的生产者写入一个数消费者立即读取并且显示我将在注释中介绍该程序的精要所在。用到的系统命名空间如下 using System;using System.Threading; 首先我们定义一个被操作的对象的类Cell在这个类里有两个方法ReadFromCell()和WriteToCell。消费者线程将调用ReadFromCell()读取cellContents的内容并且显示出来生产者进程将调用WriteToCell()方法向cellContents写入数据。 public class Cell{  int cellContents; // Cell对象里边的内容  bool readerFlag false; // 状态标志为true时可以读取为false则正在写入  public int ReadFromCell( )  {  lock(this) // Lock关键字保证了什么请大家看前面对lock的介绍  {    if (!readerFlag)//如果现在不可读取    {     try    {      file://等待WriteToCell方法中调用Monitor.Pulse()方法      Monitor.Wait(this);    }    catch (SynchronizationLockException e)    {      Console.WriteLine(e);    }    catch (ThreadInterruptedException e)    {      Console.WriteLine(e);    }    }    Console.WriteLine(Consume: {0},cellContents);    readerFlag false; file://重置readerFlag标志表示消费行为已经完成    Monitor.Pulse(this); file://通知WriteToCell()方法该方法在另外一个线程中执行等待中  }  return cellContents;  }  public void WriteToCell(int n)  {  lock(this)  {    if (readerFlag)    {    try    {      Monitor.Wait(this);    }    catch (SynchronizationLockException e)    {      file://当同步方法指Monitor类除Enter之外的方法在非同步的代码区被调用      Console.WriteLine(e);    }    catch (ThreadInterruptedException e)    {      file://当线程在等待状态的时候中止       Console.WriteLine(e);    }    }    cellContents n;    Console.WriteLine(Produce: {0},cellContents);    readerFlag true;     Monitor.Pulse(this); file://通知另外一个线程中正在等待的ReadFromCell()方法  }  }}下面定义生产者CellProd和消费者类CellCons它们都只有一个方法ThreadRun()以便在Main()函数中提供给线程的ThreadStart代理对象作为线程的入口。 public class CellProd{  Cell cell; // 被操作的Cell对象  int quantity 1; // 生产者生产次数初始化为1   public CellProd(Cell box, int request)  {  //构造函数  cell box;   quantity request;   }  public void ThreadRun( )  {  for(int looper1; looperquantity; looper)    cell.WriteToCell(looper); file://生产者向操作对象写入信息  }} public class CellCons{  Cell cell;   int quantity 1;   public CellCons(Cell box, int request)  {  cell box;   quantity request;   }  public void ThreadRun( )  {  int valReturned;  for(int looper1; looperquantity; looper)    valReturnedcell.ReadFromCell( );//消费者从操作对象中读取信息  }} 然后在下面这个类MonitorSample的Main()函数中我们要做的就是创建两个线程分别作为生产者和消费者使用CellProd.ThreadRun()方法和CellCons.ThreadRun()方法对同一个Cell对象进行操作。 public class MonitorSample{  public static void Main(String[] args)  {  int result 0; file://一个标志位如果是0表示程序没有出错如果是1表明有错误发生  Cell cell new Cell( );   //下面使用cell初始化CellProd和CellCons两个类生产和消费次数均为20次  CellProd prod new CellProd(cell, 20);   CellCons cons new CellCons(cell, 20);   Thread producer new Thread(new ThreadStart(prod.ThreadRun));  Thread consumer new Thread(new ThreadStart(cons.ThreadRun));  //生产者线程和消费者线程都已经被创建但是没有开始执行   try  {    producer.Start( );    consumer.Start( );     producer.Join( );     consumer.Join( );    Console.ReadLine();  }  catch (ThreadStateException e)  {    file://当线程因为所处状态的原因而不能执行被请求的操作    Console.WriteLine(e);     result 1;   }  catch (ThreadInterruptedException e)  {    file://当线程在等待状态的时候中止    Console.WriteLine(e);     result 1;   }  //尽管Main()函数没有返回值但下面这条语句可以向父进程返回执行结果  Environment.ExitCode result;  }} 大家可以看到在上面的例程中同步是通过等待Monitor.Pulse()来完成的。首先生产者生产了一个值而同一时刻消费者处于等待状态直到收到生产者的“脉冲(Pulse)”通知它生产已经完成此后消费者进入消费状态而生产者开始等待消费者完成操作后将调用Monitor.Pulese()发出的“脉冲”。它的执行结果很简单 Produce: 1Consume: 1Produce: 2Consume: 2Produce: 3Consume: 3......Produce: 20Consume: 20 事实上这个简单的例子已经帮助我们解决了多线程应用程序中可能出现的大问题只要领悟了解决线程间冲突的基本方法很容易把它应用到比较复杂的程序中去。 转载于:https://www.cnblogs.com/supersand/archive/2005/08/27/224185.html
http://www.pierceye.com/news/458270/

相关文章:

  • 网站建设用什么系统华为弹性云做网站
  • 莱芜高端网站建设报价网站色彩策划
  • 房地产项目网站做网站互联网公司有哪些
  • 凡科做网站友情链接怎么做wordpress广告位设置
  • org已经备案的网站wap网站建设服务
  • 企业网站模板免费下载企业网站模板免费完整版的网站模板
  • 外贸网站建设公司价格怎样做触屏版手机网站
  • 南宁站建好就够用秦皇岛微信推广平台
  • 物流公司做网站有用吗河北省住房和城乡建设网站
  • 网站举报官网seo站长论坛
  • 建站工具有哪些论坛网站建设总体要求
  • 公司网页网站建设 pptwordpress php 采集
  • 遵义网站开发公司舟山网站建设企业
  • 外贸网站一站式服务招网站建设销售
  • 绚丽的网站wordpress进入后台显示500
  • 威海城乡与住房建设部网站小颜自助建站系统
  • 域名怎么解析到网站做响应式网站需要学哪些知识
  • wordpress手机端慢seoer是什么意思
  • wordpress添加站点江苏廉政建设网站
  • 网站seo是什么做二维码推送网站
  • win7 iis默认网站设置游戏推广员
  • 湖北二师网站建设排名潍坊专业捞泵电话
  • 个人网站设计内容和要求萍乡网站制作公司
  • 合肥网站seo费用怎么把文章导入wordpress
  • 赣州网站推广哪家最专业阿里云wordpress数据库备份
  • 珠海专业网站建设公司做网站虚拟主机好还是
  • 做美图 网站有哪些wordpress哪些插件
  • 倒计时网站模板全屋定制设计培训学校哪里有
  • 凡客做网站网站排名的重要性
  • 怎么问客户做不做网站企业网站源码 多语言