Lütfen Linux'tan, Windows perspektifinden açıklayınız.
Ben C # programlıyorum, bu iki terim bir fark yaratır. Örnekler ve benzeri ile mümkün olduğunca çok posta gönderin ....
Teşekkürler
Lütfen Linux'tan, Windows perspektifinden açıklayınız.
Ben C # programlıyorum, bu iki terim bir fark yaratır. Örnekler ve benzeri ile mümkün olduğunca çok posta gönderin ....
Teşekkürler
Yanıtlar:
Windows için kritik bölümler mutekslerden daha hafiftir.
Muteksler süreçler arasında paylaşılabilir, ancak her zaman bazı ek yükleri olan çekirdeğe sistem çağrısı ile sonuçlanır.
Kritik bölümler yalnızca bir işlem içinde kullanılabilir, ancak çekişme durumunda yalnızca çekirdek moduna geçmeleri avantajına sahiptir - Yaygın durum olması gereken sınırsız satın almalar inanılmaz derecede hızlıdır. Çekişme durumunda, bir senkronizasyon ilkelini (bir olay veya semafor gibi) beklemek için çekirdeğe girerler.
İkisi arasındaki süreyi karşılaştıran hızlı bir örnek uygulama yazdım. Sistemimde 1.000.000 sınırsız satın alma ve bırakma için bir muteks bir saniyeyi alır. Kritik bir bölüm 1.000.000 kazanım için ~ 50 ms sürer.
İşte test kodu, bunu çalıştırdım ve muteks birinci veya ikinci ise benzer sonuçlar aldım, bu yüzden başka efekt görmüyoruz.
HANDLE mutex = CreateMutex(NULL, FALSE, NULL);
CRITICAL_SECTION critSec;
InitializeCriticalSection(&critSec);
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
LARGE_INTEGER start, end;
// Force code into memory, so we don't see any effects of paging.
EnterCriticalSection(&critSec);
LeaveCriticalSection(&critSec);
QueryPerformanceCounter(&start);
for (int i = 0; i < 1000000; i++)
{
EnterCriticalSection(&critSec);
LeaveCriticalSection(&critSec);
}
QueryPerformanceCounter(&end);
int totalTimeCS = (int)((end.QuadPart - start.QuadPart) * 1000 / freq.QuadPart);
// Force code into memory, so we don't see any effects of paging.
WaitForSingleObject(mutex, INFINITE);
ReleaseMutex(mutex);
QueryPerformanceCounter(&start);
for (int i = 0; i < 1000000; i++)
{
WaitForSingleObject(mutex, INFINITE);
ReleaseMutex(mutex);
}
QueryPerformanceCounter(&end);
int totalTime = (int)((end.QuadPart - start.QuadPart) * 1000 / freq.QuadPart);
printf("Mutex: %d CritSec: %d\n", totalTime, totalTimeCS);
Teorik bir bakış açısından, kritik bölüm , kod paylaşılan kaynaklara eriştiği için aynı anda birden fazla iş parçacığı tarafından çalıştırılmaması gereken bir kod parçasıdır.
Bir muteksin kritik bölümleri korumak için kullanılır (ve bazen veri yapısının adı) bir algoritmadır.
Semaforlar ve Monitörler bir muteksin ortak uygulamalarıdır.
Uygulamada, pencerelerde bulunan birçok muteks uygulaması vardır. Temel olarak uygulamalarının sonucu olarak kilitleme düzeyleri, kapsamları, maliyetleri ve farklı çekişme düzeylerindeki performansları nedeniyle farklılık gösterirler. Bkz. CLR Ters Yüz - Farklı muteks uygulamalarının maliyetlerinin bir çizelgesi için ölçeklenebilirlik için eşzamanlılığı kullanma .
Kullanılabilir senkronizasyon ilkeleri.
lock(object)
İfadesi bir kullanılarak işletilir Monitor
- bkz MSDN başvuru için.
Son yıllarda tıkanmasız senkronizasyon konusunda çok araştırma yapılmaktadır . Amaç algoritmaları kilitlemesiz veya beklemesiz bir şekilde uygulamaktır. Bu tür algoritmalarda, bir süreç diğer süreçlerin çalışmalarını bitirmesine yardımcı olur, böylece süreç sonunda çalışmasını bitirebilir. Sonuç olarak, bir süreç, bazı işler yapmaya çalışan diğer süreçler asılsa bile işini bitirebilir. Kilitler kullanıldığında, kilitlerini serbest bırakmazlar ve diğer işlemlerin devam etmesini önlerlerdi.
Diğer yanıtlara ek olarak, aşağıdaki ayrıntılar pencerelerdeki kritik bölümlere özgüdür:
InterlockedCompareExchange
operasyon kadar basitLinux'ta, kritik sayıya bir spin sayısıyla benzer bir amaca hizmet eden bir "spin kilidi" olduğunu düşünüyorum.
Kritik Bölüm ve Muteks İşletim sistemine özgü değildir, çok iş parçacığı / çok işlemli kavramları.
Kritik Bölüm , belirli bir zamanda yalnızca kendisi tarafından çalıştırılması gereken bir kod parçasıdır (örneğin, aynı anda çalışan 5 iş parçacığı ve bir diziyi güncelleyen "critical_section_function" adlı bir işlev vardır ... 5 iş parçacığının tümünü istemezsiniz Program kritik_section_function () çalıştırırken, diğer iş parçacıklarının hiçbirinin kritik_section_function işlevlerini çalıştırmaması gerekir.
mutex * Mutex, kritik bölüm kodunu uygulamanın bir yoludur (bir belirteç gibi düşünün ... thread'in kritik_seksiyon_kodunu çalıştırmak için buna sahip olması gerekir)
Muteks, bir iş parçacığının edinebildiği ve diğer iş parçacıklarının onu almasını engelleyen bir nesnedir. Zorunlu değildir, tavsiye niteliğindedir; bir iş parçacığı muteksin temsil ettiği kaynağı edinmeden kullanabilir.
Kritik bir bölüm, işletim sistemi tarafından kesilmemesini garanti eden bir kod uzunluğudur. Sahte kodda şöyle olur:
StartCriticalSection();
DoSomethingImportant();
DoSomeOtherImportantThing();
EndCriticalSection();
Linux'taki kritik seçime eşit olan 'hızlı' Windows , hızlı kullanıcı alanı muteksi anlamına gelen bir futex olacaktır . Bir futex ve mutex arasındaki fark, bir futex ile çekirdeğin yalnızca tahkim gerektiğinde dahil olması, böylece atom sayacı her değiştiğinde çekirdeğin konuşma yükünü kurtarmanızdır. Bu .. önemli bir tasarruf edebilirsiniz bazı uygulamalarda kilitleri müzakere zaman kazandırabilir.
Bir futeks, bir muteksi paylaşmak için kullanacağınız araçlar kullanılarak da süreçler arasında paylaşılabilir.
Ne yazık ki, futexlerin uygulanması çok zor olabilir (PDF). (2018 güncellemesi, 2009'daki kadar korkutucu değiller).
Bunun ötesinde, her iki platformda da hemen hemen aynı. Paylaşılan bir yapıda (umarım) açlığa neden olmayacak şekilde atomik, jetonla çalışan güncellemeler yapıyorsunuz. Geriye kalan sadece bunu gerçekleştirme yöntemidir.
Sadece 2 sent eklemek için, kritik Bölümler bir yapı olarak tanımlanır ve üzerlerindeki işlemler kullanıcı modu bağlamında gerçekleştirilir.
ntdll! _RTL_CRITICAL_SECTION + 0x000 DebugInfo: Ptr32 _RTL_CRITICAL_SECTION_DEBUG + 0x004 LockCount: Int4B + 0x008 Özyineleme Sayısı: Int4B + 0x00c OwningThread: Ptr32 Geçersiz + 0x010 LockSemaphore: Ptr32 Geçersiz + 0x014 SpinCount: Uint4B
Muteks ise Windows nesne dizininde oluşturulan çekirdek nesneleridir (ExMutantObjectType). Muteks işlemleri çoğunlukla çekirdek kipinde gerçekleştirilir. Örneğin, bir Mutex oluştururken, çekirdekte nt! NtCreateMutant'ı çağırırsınız.
Michael'dan büyük cevap. C ++ 11'de tanıtılan muteks sınıfı için üçüncü bir test ekledim. Sonuç biraz ilginçtir ve hala tek işlemler için CRITICAL_SECTION nesnelerinin orijinal onayını desteklemektedir.
mutex m;
HANDLE mutex = CreateMutex(NULL, FALSE, NULL);
CRITICAL_SECTION critSec;
InitializeCriticalSection(&critSec);
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
LARGE_INTEGER start, end;
// Force code into memory, so we don't see any effects of paging.
EnterCriticalSection(&critSec);
LeaveCriticalSection(&critSec);
QueryPerformanceCounter(&start);
for (int i = 0; i < 1000000; i++)
{
EnterCriticalSection(&critSec);
LeaveCriticalSection(&critSec);
}
QueryPerformanceCounter(&end);
int totalTimeCS = (int)((end.QuadPart - start.QuadPart) * 1000 / freq.QuadPart);
// Force code into memory, so we don't see any effects of paging.
WaitForSingleObject(mutex, INFINITE);
ReleaseMutex(mutex);
QueryPerformanceCounter(&start);
for (int i = 0; i < 1000000; i++)
{
WaitForSingleObject(mutex, INFINITE);
ReleaseMutex(mutex);
}
QueryPerformanceCounter(&end);
int totalTime = (int)((end.QuadPart - start.QuadPart) * 1000 / freq.QuadPart);
// Force code into memory, so we don't see any effects of paging.
m.lock();
m.unlock();
QueryPerformanceCounter(&start);
for (int i = 0; i < 1000000; i++)
{
m.lock();
m.unlock();
}
QueryPerformanceCounter(&end);
int totalTimeM = (int)((end.QuadPart - start.QuadPart) * 1000 / freq.QuadPart);
printf("C++ Mutex: %d Mutex: %d CritSec: %d\n", totalTimeM, totalTime, totalTimeCS);
Sonuçlarım 217, 473 ve 19 idi (son iki zamanın oranımın kabaca Michael'ınkiyle karşılaştırılabilir olduğunu, ancak makinem ondan en az dört yıl daha küçük olduğundan, 2009 ve 2013 arasında artan hızın kanıtını görebilirsiniz. , XPS-8700 çıktığında). Yeni muteks sınıfı, Windows muteksinin iki katıdır, ancak yine de Windows CRITICAL_SECTION nesnesinin onda birinden daha azdır. Sadece özyinelemesiz muteksi test ettiğimi unutmayın. CRITICAL_SECTION nesneleri özyinelemelidir (bir iş parçacığı aynı sayıda kalması koşuluyla bunları tekrar tekrar girebilir).
AC işlevlerine yalnızca gerçek parametrelerini kullanıyorsa reentrant denir.
Evresel işlevler aynı anda birden çok evre tarafından çağrılabilir.
Evresel işlev örneği:
int reentrant_function (int a, int b)
{
int c;
c = a + b;
return c;
}
Evresel olmayan fonksiyon örneği:
int result;
void non_reentrant_function (int a, int b)
{
int c;
c = a + b;
result = c;
}
C standart kitaplığı strtok () yeniden girilmez ve aynı anda 2 veya daha fazla iş parçacığı tarafından kullanılamaz.
Bazı platform SDK'ları, strtok_r () adlı strtok () 'un reentrant sürümü ile birlikte gelir;
Enrico Migliore