Приведет ли это к состоянию гонки в программировании на основе событий? - PullRequest
0 голосов
/ 05 октября 2011

Я пишу небольшую агентную симуляцию взаимодействия в дискретном симуляторе и начинаю писать код, который выглядит следующим образом.У меня раньше не было событийно-ориентированного программирования, но я действительно не наблюдал эту ситуацию.Мне интересно, приведет ли следующий фрагмент кода к состоянию гонки при обновлении значения msgRcvd.

// Following is the event-loop per-se
Controller {
    if (...) {
       SendMessage(currentTime() + 5, i,j)
       SendMessage(currentTime() + 5, i,k)
    }
    print currentTime(), msgsRcvd
    Schedule(currentTime()+1, Controller)
}

// The following function is called when an 
// agent receives a message
Receive(Agent agent) {
    if (...) {
       msgsRcvd++ // <-- this is a global variable
    }
}

Насколько я понимаю, в currentTime() + 5 оба агента получают сообщение в в то же время , потому что оба события происходят в одно и то же логическое время, поэтому я должен увидеть количество сообщений, равное 2?Или я увижу какое-то странное состояние гонки, и значение будет зависеть от планировщика (т. Е. Может закончиться выводом 1 или 2)?Есть предложения?

Ответы [ 3 ]

1 голос
/ 05 октября 2011

Нет, хотя код агента очень подозрительный и выглядит опасным, я не вижу, чтобы в этом случае вызывал состояние гонки: msgsRcvd всегда должно заканчиватьсяправильная сумма.Даже если планировщик прерывает agent1 непосредственно перед приращением, мне кажется, что управление всегда вернется, чтобы завершить это приращение.Если контроллер получает управление, то может случиться так, что он сообщит о неточном содержимом MsgsRcvd, но что с того?MsgsRcvd быстро возвращается в фазу.

Хотя это действительно страшный кусок кода.Когда я смотрю на этот вид кода, я всегда хочу переместить инкремент MsgsRcvd в контроллер, открывая там функцию, которая будет делать инкремент.Но это только заставило бы меня чувствовать себя лучше в этом случае;это не изменило бы логику и не решило бы «проблему» (если она есть) временного неточности MsgsRcvd.

1 голос
/ 05 октября 2011

Первоначально собирался упомянуть, что не существует языка / платформы, не зависящего от языка, чтобы ответить на этот вопрос, но Эрик Дж. Об этом рассказал.

В C ++ этот написанный код не будет безопасным, если ваша платформа не гарантирует, что обратные вызовы будут сериализованы. Причина в том, что оператор приращения не является атомарным, и если два потока одновременно пытаются обновить значение, может произойти любое количество вещей в зависимости от порядка выборки, добавления и сохранения.

Если эта платформа действительно была разработана с учетом параллелизма, то должен существовать «взаимосвязанный / атомарный» API, обеспечивающий необходимую вам функцию.

1 голос
/ 05 октября 2011

Ответ зависит от реализации вашего транспорта событий и в этом смысле не зависит от языка.

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

Если в вашей очереди событий есть какой-то интеллект, который пытается консолидировать события на основеотметка времени, вы увидите только одно событие в получающем агенте.Мне неизвестна обычная система, которая это делает (хотя некоторые системы пользовательского интерфейса могут, например, объединить два быстрых щелчка мышью в двойной щелчок ... но это специфическое поведение конкретной системы событий, а не язык / платформа независимо от платформы).

...