Bir muteks diğer sorunları çözmek için kullanılabilirken, var olmalarının temel nedeni karşılıklı dışlama sağlamak ve böylece bir yarış koşulu olarak bilinen şeyi çözmek. İki (veya daha fazla) iş parçacığı veya işlem aynı değişkene aynı anda erişmeye çalıştığında, bir yarış durumu potansiyeline sahibiz. Aşağıdaki kodu düşünün
//somewhere long ago, we have i declared as int
void my_concurrently_called_function()
{
i++;
}
Bu işlevin iç kısımları çok basit görünüyor. Bu sadece bir açıklama. Ancak, tipik bir sözde derleme dili eşdeğeri şunlar olabilir:
load i from memory into a register
add 1 to i
store i back into memory
Eşdeğer montaj dili komutlarının tümü i üzerinde artış işlemini gerçekleştirmek için gerekli olduğundan, i'yi artırmanın atmoik olmayan bir işlem olduğunu söylüyoruz. Bir atomik işlem, talimatın yürütülmesi başladıktan sonra bir garantinin kesintiye uğramamasıyla donanım üzerinde tamamlanabilen bir işlemdir. Artış i, 3 atom komutundan oluşan bir zincirden oluşur. Birçok iş parçacığının işlevi çağırdığı eşzamanlı bir sistemde, iş parçacığı yanlış zamanda okuduğunda veya yazdığında sorunlar oluşur. Aynı anda çalışan iki iş parçacığımız olduğunu ve birinin işlevi birbiri ardına çağırdığını düşünün. Ayrıca, 0 olarak başlattığımızı da söyleyelim. Ayrıca, çok sayıda kayıt bulunduğumuzu ve iki iş parçacığının tamamen farklı kayıtlar kullandığını varsayalım, böylece çarpışma olmayacak. Bu olayların gerçek zamanlaması şunlar olabilir:
thread 1 load 0 into register from memory corresponding to i //register is currently 0
thread 1 add 1 to a register //register is now 1, but not memory is 0
thread 2 load 0 into register from memory corresponding to i
thread 2 add 1 to a register //register is now 1, but not memory is 0
thread 1 write register to memory //memory is now 1
thread 2 write register to memory //memory is now 1
Olan şey, i'yi aynı anda arttıran iki iş parçacığımız var, işlevimiz iki kez çağrılıyor, ancak sonuç bu gerçekle tutarsız. Fonksiyon sadece bir kez çağrılmış gibi görünüyor. Bunun nedeni, atomikliğin makine düzeyinde "kırılmasıdır", yani dişlerin birbirini kesebileceği veya yanlış zamanlarda birlikte çalışabileceği anlamına gelir.
Bunu çözmek için bir mekanizmaya ihtiyacımız var. Yukarıdaki talimatlara biraz sipariş vermeliyiz. Yaygın bir mekanizma, biri hariç tüm dişleri engellemektir. Pthread mutex bu mekanizmayı kullanır.
Paylaşılan değerleri aynı anda diğer iş parçacıkları tarafından güvensiz olarak değiştirebilecek bazı kod satırlarını yürütmesi gereken her iş parçacığı (karısıyla konuşmak için telefonu kullanarak), önce bir muteks üzerinde kilit kazanmalıdır. Bu şekilde, paylaşılan verilere erişim gerektiren tüm evreler muteks kilidinden geçmelidir. Ancak bundan sonra bir iş parçacığı kodu yürütebilir. Kodun bu bölümüne kritik bölüm denir.
İş parçacığı kritik bölümü yürüttükten sonra, başka bir iş parçacığının muteks üzerinde kilit alabilmesi için muteks üzerindeki kilidi serbest bırakması gerekir.
Gerçek, fiziksel nesnelere münhasır erişim isteyen insanlar düşünülürken muteksi olma kavramı biraz garip görünüyor, ancak programlama yaparken kasıtlı olmalıyız. Eşzamanlı iş parçacıkları ve süreçler, yaptığımız sosyal ve kültürel yetiştiriciliğe sahip değildir, bu yüzden verileri güzel bir şekilde paylaşmaya zorlamalıyız.
Teknik olarak konuşursak, bir muteks nasıl çalışır? Daha önce bahsettiğimiz aynı yarış koşullarından muzdarip değil mi? Pthread_mutex_lock () bir değişkenin basit bir artışından biraz daha karmaşık değil mi?
Teknik olarak, bize yardımcı olmak için bazı donanım desteğine ihtiyacımız var. Donanım tasarımcıları bize birden fazla şey yapan ancak atomik olduğu garanti edilen makine talimatları veriyorlar. Böyle bir talimatın klasik bir örneği test ve settir (TAS). Bir kaynak üzerinde bir kilit elde etmeye çalışırken, TAS'yi kullanarak bellekteki bir değerin 0 olup olmadığını kontrol edebiliriz. Eğer öyleyse, kaynağın kullanımda olduğunu gösteren işaretimiz olacaktır ve hiçbir şey yapmıyoruz (veya daha doğru bir şekilde Bir mekanizma tarafından bekleriz. Bir pthreads mutex, işletim sistemindeki özel bir sıraya girmemizi sağlar ve kaynak kullanılabilir olduğunda bizi bilgilendirir. Dümen sistemleri, durumu tekrar tekrar test etmemizi gerektirebilir. . Bellekteki değer 0 değilse, TAS başka bir talimat kullanmadan konumu 0 dışında bir değere ayarlar. O' Bize atomiklik kazandırmak için iki montaj talimatını 1'de birleştirmek gibi. Bu nedenle, değerin test edilmesi ve değiştirilmesi (eğer uygunsa) başladıktan sonra kesilemez. Muteksleri böyle bir talimatın üzerine inşa edebiliriz.
Not: bazı bölümler daha önceki bir cevaba benzer görünebilir. Düzenleme davetini kabul ettim, orijinal şeklini tercih etti, bu yüzden biraz da verbiage ile aşılanmış olanı koruyorum.