Что случилось с этой фиксацией для проверенной дважды блокировки?

Используя ответы Денниса Уильямсона и Альберто Закканьи, я придумал следующий сценарий, который преобразует все файлы указанного типа из всех подкаталогов. Затем выходные данные собираются в одну папку, которая задается как /path/to/destination

mkdir /path/to/destination
for a in $(find . -name "*.php"); 
do 
        filename=$(basename $a);
        echo $filename
        iconv -f iso-8859-1 -t utf-8 <"$a" >"/path/to/destination/$filename"; 
done

. Базовое имя функции возвращает имя файла без пути к файлу.

Альтернатива (интерактивная): Теперь я также создал интерактивный сценарий пользователя, который позволяет вам решить, хотите ли вы перезаписать старые файлы или просто переименовать их. Дополнительная благодарность идет в tbsalling

for a in $(find . -name "*.tex");
do
        iconv -f iso-8859-1 -t utf-8 <"$a" >"$a".utf8 ;
done
echo "Should the original files be replaced (Y/N)?"
read replace
if [ "$replace" == "Y" ]; then
    echo "Original files have been replaced."
    for a in $(find . -name "*.tex.utf8");
        do
            file_no_suffix=$(basename -s .tex.utf8 "$a");
            directory=$(dirname "$a");
            mv "$a" "$directory"/"$file_no_suffix".tex;
        done
else
        echo "Original files have been converted and converted files were saved with suffix '.utf8'"
fi

Удачи с этим, и я был бы благодарен за любые комментарии, чтобы улучшить его, спасибо!

5
задан GingerPlusPlus 13 February 2016 в 16:44
поделиться

3 ответа

Ваше исправление ничего не исправляет, так как запись в sync_check и экземпляр может выполняться не по порядку на ЦП. В качестве примера представьте, что первые два вызова instance происходят примерно в одно и то же время на двух разных процессорах. Первый поток получит блокировку, инициализирует указатель и установит для sync_check значение true именно в этом порядке, но процессор может изменить порядок записи в память. На другом процессоре второй поток может проверить sync_check, убедиться, что это правда, но экземпляр еще не может быть записан в память. Подробнее см. Замечания по программированию без блокировки для Xbox 360 и Microsoft Windows .

Указанное вами решение sync_check для конкретного потока должно работать тогда (при условии, что вы инициализируете указатель на 0).

5
ответ дан 14 December 2019 в 13:45
поделиться

Здесь есть отличное чтение (хотя оно ориентировано на .net / C #): http://msdn.microsoft.com/en-us/magazine/cc163715.aspx

. Это сводится к тому, что вам нужно иметь возможность сообщить ЦП, что он не может переупорядочить ваши чтения / записи для доступа к этой переменной (начиная с оригинального Pentium, ЦП может переупорядочивать определенные инструкции, если считает, что логика будет быть незатронутым), и что он должен гарантировать, что кеш согласован (не забывайте об этом - мы, разработчики, можем притвориться, что вся память - это всего лишь один плоский ресурс, но на самом деле каждое ядро ​​ЦП имеет кеш, некоторые неразделенные (L1), некоторые могут иногда использоваться совместно (L2)) - ваша инициализация может записывать в основную оперативную память, но другое ядро ​​может иметь неинициализированное значение в кеше. Если у вас нет семантики параллелизма, ЦП может не знать, что его кеш грязный.

Я не знаю стороны C ++, но в .net вы бы обозначили переменную как изменчивую, чтобы защитить доступ к ней (или вы использовали бы чтение из памяти / написать барьерные методы в System.Threading).

Кстати, я читал, что в .net 2.0 блокировка с двойной проверкой гарантированно работает без "изменчивых" переменных (для любых читателей .net) - это не поможет вам с вашим кодом на C ++ .

Если вы хотите быть в безопасности, вам нужно будет сделать аналог C ++, пометив переменную как изменчивую в C #.

1
ответ дан 14 December 2019 в 13:45
поделиться

«Последний случай нарушает идиому - два потока могут в конечном итоге создать синглтон».

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

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

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

I '

0
ответ дан 14 December 2019 в 13:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: