$dom = new DOMDocument;
$dom->loadXML($xml);
$dom->getElementsByTagName('root')->item(0)
->removeChild($dom->getElementsByTagName('remove')->item(0));
Это очень специфично. Вы можете использовать XPath, если вам нужна общая общность:
foreach ($xpath->query('//remove') as $node) {
$node->parentNode->removeChild($node);
}
Конкретно для x86 и в отношении вашего примера: counter ++
, есть несколько способов его компиляции. Самый тривиальный пример:
inc counter
Это переводится в следующие микрооперации:
счетчик
в скрытый регистр на ЦП counter
Это по сути то же самое, что:
mov eax, counter
inc eax
mov counter, eax
Обратите внимание, что если какой-либо другой агент обновит счетчик
между загрузкой и хранилищем, он выиграет ' t отражается в счетчике
после накопления. Этот агент может быть другим потоком в том же ядре, другим ядром в том же процессоре, другим процессором в той же системе или даже каким-то внешним агентом, который использует DMA (прямой доступ к памяти).
Если вы хотите гарантировать, что это inc
является атомарным, используйте префикс lock
:
lock inc counter
lock
гарантирует, что никто не сможет обновить счетчик
между загрузкой и хранилищем.
Что касается более сложные инструкции, вы обычно не можете предположить, что они будут выполняться атомарно, если они не поддерживают префикс lock
.
Ответ: это зависит!
Вот некоторая путаница в том, что такое инструкция ассемблера. Обычно одна инструкция ассемблера транслируется ровно в одну машинную инструкцию. Исключение составляют случаи, когда вы используете макросы, но вы должны об этом знать.
Тем не менее, вопрос сводится к тому, что одна машинная инструкция атомарна?
В старые добрые времена так и было. Но сегодня со сложными процессорами, длительными инструкциями, гиперпоточностью ... это не так. Некоторые процессоры гарантируют, что некоторые инструкции увеличения / уменьшения являются атомарными. Причина в том, что они удобны для очень простой синхронизации.
Также некоторые команды ЦП не так проблемны. Когда у вас есть простая выборка (одного фрагмента данных, который процессор может получить одним фрагментом) - сама выборка, конечно, атомарна, потому что делить нечего. Но когда у вас есть невыровненные данные, все снова становится сложным.
Ответ: это зависит от обстоятельств. Внимательно прочтите инструкцию производителя по эксплуатации машины. Сомневаюсь, что это не так!
Редактировать: Ой, я сейчас это видел, вы тоже просите счетчик ++. Высказыванию «скорее всего, будет переведено» вообще нельзя верить. Конечно, это во многом зависит и от компилятора! Это становится труднее, когда компилятор выполняет различные оптимизации.
Возможно, это не настоящий ответ на ваш вопрос, но (при условии, что это C # или другой язык .NET), если вы хотите, чтобы counter ++
действительно был многопоточным атомарным , вы можете использовать System.Threading.Interlocked.Increment (counter)
.
См. другие ответы для получения актуальной информации о множестве различных способов, почему / как counter ++
не может быть атомарным. ; -)
На многих других процессорах разделение между системой памяти и процессором больше. (часто этот процессор может быть малым или прямым в зависимости от системы памяти, такой как ARM и PowerPC), это также имеет последствия для атомарного поведения, если система памяти может переупорядочивать операции чтения и записи.
Для этого существуют барьеры памяти ( http://en.wikipedia.org/wiki/Memory_barrier )
Короче говоря, в то время как атомарные инструкции достаточно на Intel (с соответствующими префиксы блокировки), необходимо сделать больше для не-Intel, так как операции ввода-вывода памяти могут быть в другом порядке.
Это известная проблема при переносе решений без блокировки с Intel на другие архитектуры.
(Обратите внимание, что многопроцессорные (не многоядерные) системы на x86, похоже, также нуждаются в барьерах памяти, по крайней мере, в 64-битном режиме.
Нет, вы не можете этого предположить. Если это четко не указано в спецификации компилятора. Более того, никто не может гарантировать, что одна-единственная инструкция ассемблера действительно атомарна. На практике каждая инструкция ассемблера транслируется в число операций микрокода - упс.
Также проблема состояния гонки тесно связана с моделью памяти (согласованность, последовательность, согласованность выпуска и т. Д.), Для каждой из них ответ и результат могут быть разными.
Аннулировано комментарием Натана:
Если я правильно помню свой ассемблер Intel x86, инструкция INC работает только с регистрами и не работает напрямую с ячейками памяти.
Таким образом, счетчик ++ не будет отдельной инструкцией в ассемблере (просто игнорируя часть постинкремента. ). Это будет как минимум три инструкции: загрузить переменную счетчика в регистр, увеличить регистр, загрузить регистр обратно в счетчик. И это только для архитектуры x86.
Короче говоря, не полагайтесь на его атомарность, если это не указано в спецификации языка и что используемый компилятор не поддерживает спецификации.
Другая проблема заключается в том, что если вы не объявите переменную как изменчивую, сгенерированный код, вероятно, не будет обновлять память при каждой итерации цикла, только в конце цикла память будет обновлено.
Я думаю, что вы получите состояние гонки при доступе.
Если вы хотите обеспечить атомарную операцию при увеличении счетчика, вам нужно будет использовать ++ counter.
]Не всегда - на некоторых архитектурах одна инструкция сборки транслируется в одну инструкцию машинного кода, а на других - нет.
Вдобавок - вы не можете никогда предполагать, что используемый вами программный язык компилирует кажущуюся простой строчку кода в одну инструкцию ассемблера. Более того, на некоторых архитектурах нельзя предполагать, что один машинный код будет выполняться атомарно.
Вместо этого используйте правильные методы синхронизации, в зависимости от языка, на котором вы кодируете.