Я беспокоился о состоянии гонки в приложении, которое я разрабатываю, когда задавался вопросом об этом вопросе.
Допустим, у меня есть большой массив или какая-то коллекция, которой управляет один компонент моей программы, назовем этот компонент Monitor. Его работа состоит в том, чтобы регулярно проверять, является ли коллекция "грязной", т.е. е. недавно изменился, и если это так, запишите моментальный снимок на диск (чтобы проверить приложение в случае сбоя) и пометьте его как «чистый» снова.
Другие компоненты той же программы, работающие в другом потоке, вызывают методы Monitor для добавления или изменения данных в массиве / коллекции. Эти методы помечают коллекцию как грязную.
Теперь методы изменения выполняются в потоках других компонентов, верно? И если мне не так повезет, они могут быть вызваны во время записи снимка на диск, изменить данные, которые уже были записаны, установить грязный флаг, и поток монитора сбрасывает его сразу после этого, не сохранив изменения (это был уже мимо элемента, когда он изменился). Итак, у меня есть грязная коллекция, помеченная как чистая.
Некоторое время я думал, что, возможно, смогу решить проблему, сделав временную копию коллекции, пометив ее как чистую, а затем отправив и сериализовав копию. Но будет ли копирование атомарным, т.е. е. могу ли я быть уверен, что коллекция не изменится, пока я ее копирую?
Между тем, я думаю, что нашел лучшие решения, как
- установка флага блокировки перед началом записи на диск и заставление методов изменения данных ждать, пока флаг не будет установлен
- имеет методы изменения данных, которые записывают в "очередь изменений", а не напрямую в коллекцию, и имеют поток, который выполняет процесс записи на диск, который ставит в очередь
и я думаю, что флаг блокировки может быть лучшим способом. Но мне все еще любопытно: копирование переменной атомарно?
Продолжение : Может быть, это должно идти само по себе, но на самом деле это очень похоже. Согласно ответам ниже, мой подход "флаг блокировки" также может не работать, верно? Потому что метод изменения данных может проверить флаг блокировки, пока он установлен на значение «заблокировано», и решить, что он не заблокирован. Поэтому мне нужна специальная конструкция, такая как мьютекс, если я действительно хочу сделать это правильно, верно?
Престижность Эриксон за его очень полезный ответ в моем последующем. Я действительно должен был задать эти два вопроса, чтобы я мог принять два ответа. Пожалуйста, проголосуйте и за него.