什么是条件同步?

有人可以向我解释条件同步吗?

一个例子(最好是在C#中)也将非常受欢迎。

听起来你的教授正在谈论线程。 线程使计算机程序一次可以执行多个操作。 在一个已经运行的情况下启动新线程的行为被计算机程序员称为“旋转线程”。

线程可以共享相同的内存空间。 条件同步(或仅仅是同步)是保护内存区域不被同时由两个不同线程修改的任何机制。

假设你在外面购物,妻子在家里付账单。 这是一个天真的例子,它在现实生活中并没有真正起作用,但它将作为一个简单的例子。

你的妻子正在网上支付账单。 与此同时,您正在杂货店刷信用卡。 这两种行为都涉及将钱从支票账户中转出。 要模拟此活动,我们编写以下代码:

public class MyBanking { static double myAccountBalance; // public void DebitAccount(double debitAmount) { Console.Writeline("Your Old Balance is: " + myAccountBalance.ToString()); Console.Writeline("Your Debit is: " + debitAmount.ToString()); myAccountBalance = myAccountBalance - amount; Console.Writeline("Your New Balance is: " + myAccountBalance.ToString()); } } 

假设您的妻子在一个线程上运行此类的一个实例(“复制”),您正在另一个线程上运行实例。 myAccountBalance变量被声明为static,以允许它在两个正在运行的实例之间共享(您和您的妻子只有一个支票帐户)。

您可以通过调用以下代码来进行借记:

 MyBanking bankingObject = new MyBanking(); bankingObject.DebitAccount(100); 

你的妻子在同一时间扣款:

 MyBanking bankingObject = new MyBanking(); bankingObject.DebitAccount(50); 

如果您的妻子的线程在屏幕上打印旧余额后,但在打印新余额之前,您的线程会被打断,会发生什么? 你妻子的post借记帐户并将控制权交还给你的post。 你的妻子在屏幕上看到这个:

 Your Old Balance is: 2000 Your Debit is: 50 Your New Balance Is: 1950 

当计算机在屏幕上打印新余额时,这将是错误的,因为您的妻子的借记也将被计算在内。 你会看到这样的东西:

 Your Old Balance is: 2000 Your Debit is: 100 Your New Balance Is: 1850 

要解决这个问题,我们使用lock语句包含方法代码。 lock语句会导致所有其他线程等待我们的实例完成。 新代码如下所示:

 public class MyBanking { static double myAccountBalance; // public void DebitAccount(double debitAmount) { lock (this) { Console.Writeline("Your Old Balance is: " + myAccountBalance.ToString()); Console.Writeline("Your Debit is: " + debitAmount.ToString()); myAccountBalance = myAccountBalance - amount; Console.Writeline("Your New Balance is: " + myAccountBalance.ToString()); } } } 

在妻子的代码开始执行之前,您妻子的线程现在将等待锁定语句中的代码完成执行。 您的新余额现在将是正确的,因为在您完成交易时,您妻子的线程不再可能更改余额。 在屏幕上,您现在将看到:

 Your Old Balance is: 2000 Your Debit is: 100 Your New Balance Is: 1900 

你的妻子会看到这个:

 Your Old Balance is: 1900 Your Debit is: 50 Your New Balance Is: 1850 

这是同步。

基本上它是需要的线程的设计模式

a)同步对资源的访问

b)有时等待其他线程,直到满足某些条件

你在C#上下文中提出这个问题,.NET使用Monitor.Wait和Monitor.Pulse(以及WaitEventhandle等各种Win32对象的包装器)为此提供支持。

这是SO上一个不错的队列示例 。

主要技术细节如下:

 lock(buffer) // is Monitor.Enter(buffer) ... finally Monitor.Leave(buffer) { while (buffer.Count < 1) { Monitor.Wait(buffer); } ... } 

注意那里有一个等待锁定的方式。 它看起来像一个死锁,但Wait会在等待时释放锁定。 lock() { }的代码在运行时仍然具有对缓冲区的独占访问权限。

然后另一个线程必须在它将某些内容放入缓冲区时发出信号:

 Monitor.Pulse(buffer); 

上面的代码几乎是正确的,但实际上是错误的。 通过使用lock(this) ,您将只锁定MyBanking类的实例,但您的妻子将锁定她的。 要锁定对共享变量的访问,您可以锁定类型(即lock(typeof(MyBanking)) )或者您可以引入一个新的共享变量并锁定(您无法锁定int,因此通常人们创建一个对象,如下所示。

 class MyBanking { static object lockObj = new object(); static double myAccountBalance; public void DebitAccount(double debitAmount) { lock (lockObj) 

已经清楚地解释了同步。 但是, 条件同步特别指示进程/线程在满足某些条件后才执行。 通常,条件是某些其他进程/线程已经执行。

在给定帐户和查看余额的给定示例中。 如果您的余额查看是一个单独的同步方法,并且我们只想在您的帐户被扣款后查看余额,那么这将需要条件同步。

生产者 – 消费者问题很好地描述了条件同步。