Что такое условие синхронизации? - PullRequest
5 голосов
/ 23 мая 2009

Может ли кто-нибудь объяснить мне синхронизацию условий?

Пример (желательно на C #) также был бы очень признателен.

Ответы [ 4 ]

9 голосов
/ 23 мая 2009

Похоже, ваш профессор говорит о потоках. Многопоточность позволяет компьютерным программам выполнять больше чем одну вещь одновременно. Процесс запуска нового потока, когда он уже запущен, программистами называется "раскручивание потока".

Потоки могут совместно использовать одно и то же пространство памяти. Условная синхронизация (или просто синхронизация) - это любой механизм, который защищает области памяти от изменения двумя разными потоками одновременно.

Допустим, вы ходите по магазинам, а жена дома оплачивает счета. Это наивный пример, и он в действительности не работает таким образом в реальной жизни, но он послужит простой иллюстрацией.

Ваша жена оплачивает счет онлайн. В то же время вы проводите свою кредитную карту в продуктовом магазине. Оба акта связаны с переводом денег с вашего текущего счета. Чтобы смоделировать это действие, мы пишем следующий код:

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 объявлена ​​статической, чтобы разрешить ее совместное использование между обоими запущенными экземплярами (у вас и вашей жены есть только один текущий счет).

Вы делаете свой дебет, вызывая код как это:

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

Ваша жена одновременно дебетует:

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

Что произойдет, если ваша нить прервется нитью вашей жены после того, как ваш старый баланс будет напечатан на экране, но до того, как новый баланс будет напечатан? Тема вашей жены списывает средства с аккаунта и возвращает управление вашей ветке. Ваша жена видит это на экране:

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. Оператор блокировки заставляет все другие потоки ждать завершения нашего экземпляра. Новый код выглядит следующим образом:

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

Это синхронизация.

2 голосов
/ 23 мая 2009

В основном это шаблон проектирования для потоков, которым требуется

а) синхронизировать доступ к ресурсу

б) иногда ждать других потоков, пока не будут выполнены определенные условия

Вы спрашиваете об этом в контексте C #, .NET предоставляет поддержку для этого с Monitor.Wait и Monitor.Pulse (и с обертками вокруг различных объектов Win32, таких как WaitEventhandle).

Вот хороший пример очереди на SO.

Основные технические детали выглядят так:

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

Обратите внимание на то, что там есть функция «В ожидании пока заблокирована». Это похоже на тупик, но Wait снимет блокировку в ожидании. Код внутри lock() { } по-прежнему имеет монопольный доступ к буферу при запуске.

И тогда другой поток должен сигнализировать, когда он помещает что-то в буфер:

Monitor.Pulse(buffer);
1 голос
/ 07 ноября 2013

Синхронизация уже была четко объяснена. Однако условие синхронизации определенно диктует, что процесс / поток выполняет только после выполнения некоторого условия. Обычно условие состоит в том, что какой-то другой процесс / поток уже выполнен.

В приведенном примере списания средств со счета и просмотра баланса. Если просмотр вашего баланса был отдельным синхронизированным методом, и мы хотели просмотреть баланс только после того, как ваш счет был списан, то для этого потребуется синхронизация условий.

Синхронизация условий очень хорошо описана проблемой производитель-потребитель .

1 голос
/ 26 февраля 2011

Код выше почти правильный, но на самом деле неверный. Используя lock(this), вы блокируете только свой экземпляр класса MyBanking, а ваша жена - его. Чтобы заблокировать доступ к общей переменной, вы можете либо заблокировать тип (т.е. lock(typeof(MyBanking))), либо ввести новую общую переменную и заблокировать ее (вы не можете заблокировать int, поэтому обычно люди создают объект следующим образом.

class MyBanking
{
    static object lockObj = new object();
    static double myAccountBalance;
    public void DebitAccount(double debitAmount)
    {
        lock (lockObj)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...