Scheff'ın cevabı kodunuzu nasıl düzelteceğinizi açıklar. Bu durumda gerçekte neler olduğuna dair biraz bilgi ekleyeceğimi düşündüm.
Optimizasyon seviyesi 1 ( ) kullanarak kodunuzu godbolt'ta derledim-O1
. İşleviniz şöyle derlenir:
func():
cmp BYTE PTR finished[rip], 0
jne .L4
.L5:
jmp .L5
.L4:
mov eax, 0
ret
Peki, burada neler oluyor? İlk olarak, bir karşılaştırmamız var: cmp BYTE PTR finished[rip], 0
- Bu finished
, yanlış olup olmadığını kontrol eder .
Eğer öyleyse değil yanlış (aka true) biz ilk çalıştırmada döngü çıkmak gerekir. Bu gerçekleştirilir göre jne .L4
olan j umps N ot e etikete Qual .L4
değeri burada i
( 0
) daha sonra kullanmak ve ve fonksiyon için bir kayıt saklanır.
O takdirde ise ancak yanlış, biz taşımak
.L5:
jmp .L5
Bu, .L5
atlama komutunun kendisi olan etiketlemek için koşulsuz bir atlamadır .
Başka bir deyişle, iş parçacığı sonsuz meşgul döngüsüne konur.
Peki bu neden oldu?
İyileştirici ile ilgili olarak, dişler tasarımının dışındadır. Diğer iş parçacıklarının eşzamanlı olarak değişkenleri okumadığını veya yazmadığını varsayar (çünkü bu, veri yarışı UB olacaktır). Erişimleri optimize edemeyeceğini söylemelisiniz. Scheff'in cevabı burada devreye giriyor. Onu tekrarlamak için uğraşmayacağım.
Optimize ediciye, finished
değişkenin işlevin yürütülmesi sırasında potansiyel olarak değişebileceği söylenmediğinden finished
, işlevin kendisi tarafından değiştirilmediğini görür ve sabit olduğunu varsayar.
Optimize edilmiş kod, işleve sabit bir bool değeriyle girilmesinden kaynaklanacak iki kod yolunu sağlar; ya döngüyü sonsuz olarak çalıştırır ya da döngü asla çalıştırılmaz.
en -O0
(beklendiği gibi) derleyici uzaklıkta halka gövdesi ve karşılaştırma optimize etmez:
func():
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], 0
.L148:
movzx eax, BYTE PTR finished[rip]
test al, al
jne .L147
add QWORD PTR [rbp-8], 1
jmp .L148
.L147:
mov rax, QWORD PTR [rbp-8]
pop rbp
ret
bu nedenle fonksiyon, optimize edilmediğinde, burada atomisite eksikliği tipik olarak bir problem değildir, çünkü kod ve veri tipi basittir. Muhtemelen burada karşılaşabileceğimiz en kötü, bir olması gereken i
şey tarafından kapalı bir değerdir .
Veri yapılarına sahip daha karmaşık bir sistemin bozuk veri veya yanlış yürütme ile sonuçlanma olasılığı daha yüksektir.