Neden pthreads'nin koşul değişkeni işlevleri muteks gerektirir?


182

Ben okuyorum pthread.h; koşul değişkeni ile ilgili işlevler (gibi pthread_cond_wait(3)) bağımsız değişken olarak bir muteks gerektirir. Neden? Anlayabildiğim kadarıyla, sadece bu argüman olarak kullanmak için bir muteks yaratacağım ? Muteksin ne yapması gerekiyor?

Yanıtlar:


194

Koşul değişkenlerinin uygulanma (veya başlangıçta) şekli budur.

Muteks, koşul değişkeninin kendisini korumak için kullanılır . Bu yüzden beklemeden önce kilitli olmanız gerekiyor.

Bekleme, muteksin "atomik olarak" kilidini açarak diğerlerinin koşul değişkenine erişmesini sağlar (sinyal için). Daha sonra koşul değişkeni sinyal verildiğinde veya yayınlandığında, bekleme listesindeki bir veya daha fazla iş parçacığı uyandırılacak ve muteks o iş parçacığı için yeniden sihirli bir şekilde kilitlenecektir.

Genellikle, nasıl çalıştığını gösteren koşul değişkenleriyle aşağıdaki işlemi görürsünüz. Aşağıdaki örnek, bir koşul değişkenine bir sinyal yoluyla iş verilen bir işçi iş parçacığıdır.

thread:
    initialise.
    lock mutex.
    while thread not told to stop working:
        wait on condvar using mutex.
        if work is available to be done:
            do the work.
    unlock mutex.
    clean up.
    exit thread.

Bekleme döndüğünde kullanılabilir olan bazı durumlar varsa, iş bu döngü içinde yapılır. İş parçacığı iş yapmayı durdurmak için işaretlendiğinde (genellikle başka bir iş parçacığı tarafından çıkış koşulunu ayarlayıp daha sonra bu değişkeni uyandırmak için koşul değişkenini tekmelemek), döngü çıkacak, muteksin kilidi açılacak ve bu iş parçacığı çıkacaktır.

Yukarıdaki kod tek tüketici modelidir, çünkü iş yapılırken muteks kilitli kalır. Çok tüketicili bir varyasyon için örnek olarak şunları kullanabilirsiniz :

thread:
    initialise.
    lock mutex.
    while thread not told to stop working:
        wait on condvar using mutex.
        if work is available to be done:
            copy work to thread local storage.
            unlock mutex.
            do the work.
            lock mutex.
    unlock mutex.
    clean up.
    exit thread.

bu da diğer tüketicilerin iş yaparken iş almasını sağlar.

Condition değişkeni, bir şeyin gerçekleşmesi gerektiğinde başka bir iş parçacığının sizi bilgilendirmesine izin vermek yerine bazı koşulları yoklama yükünü ortadan kaldırır. Başka bir iş parçacığı, iş parçacığının aşağıdaki gibi kullanılabilir olduğunu söyleyebilir:

lock mutex.
flag work as available.
signal condition variable.
unlock mutex.

Genellikle yanlış uyandırma olarak adlandırılanların büyük çoğunluğu genellikle her zaman pthread_cond_waitçağrılarında (yayın) birden çok iş parçacığının sinyal verilmiş olması , bir kişinin muteks ile geri dönmesi, işi yapması ve tekrar beklemesi idi.

Daha sonra yapılacak iş olmadığında, sinyal verilen ikinci iplik ortaya çıkabilir. Bu yüzden, işin yapılması gerektiğini belirten ekstra bir değişkeniniz olması gerekiyordu (bu, burada condvar / mutex çifti ile doğal olarak muteks korumalıydı - ancak muteksi değiştirmeden önce kilitlemek için diğer dişler).

O was bir iş parçacığı başka bir işlem tarafından tekme olmadan bir koşul bekleyin dönmek için Pthreads üzerinde çalışıyor, hem gelişiminde / kod servis ve bir kullanıcı olarak tüm benim yıllardır, (bu gerçek bir sahte uyandırma) ama teknik olarak mümkün bunlardan hiç birini almadım. Belki de bunun nedeni HP'nin iyi bir uygulaması olmasıydı :-)

Her halükarda, hatalı davayı işleyen aynı kod, orijinal sahte uyandırma işlemlerini de gerçekleştirdi, çünkü bunlar için kullanılabilir bayrak ayarlanmayacaktı.


3
'bir şeyler yap' while döngüsünün içinde olmamalıdır. While döngünüzün sadece durumu kontrol etmesini istersiniz, aksi takdirde sahte bir uyanma alırsanız 'bir şeyler yapabilirsiniz'.
nos

1
Hayır, hata işleme ikinci sıradadır. Pthreads ile, belirgin bir sebep olmadan (sahte bir uyandırma) ve herhangi bir hata olmadan uyandırılabilirsin. Böylece uyandıktan sonra 'bazı koşulları' tekrar kontrol etmeniz gerekir.
nos

1
Anladığımdan emin değilim. Nos ile aynı reaksiyonu yaşadım ; neden döngü do somethingiçinde while?
ELLIOTTCABLE

1
Belki de yeterince açıklığa kavuşturmuyorum. Döngü, işin hazır olmasını beklemek değildir , böylece yapabilirsiniz. Döngü ana "sonsuz" çalışma halkasıdır. Cond_wait öğesinden dönerseniz ve çalışma bayrağı ayarlanmışsa, işi yaparsınız ve tekrar dolaşırsınız. "while some condition" yalnızca iş parçacığının muteksi ve büyük olasılıkla çıkacağı noktada çalışmayı bırakmasını istediğinizde yanlış olur.
paxdiablo

7
@stefaanv "muteks hala koşul değişkenini korumak içindir, onu korumanın başka bir yolu yoktur": muteks koşul değişkenini korumak değildir ; yüklem verilerini korumaktır , ancak bence bu ifadeyi izleyen yorumunuzu okumanızı biliyorsunuzdur. Yasal olarak bir koşul değişkeni sinyal ve tam uygulamaları tarafından desteklenen olabilir sonrası yüklemi sarma muteksin -Unlock ve aslında, olur edeceğiz rahatlatmak bazı durumlarda bunu yaparken çekişme.
WhozCraig

59

Bir koşul değişkeni yalnızca bir koşulu işaretleyebiliyorsanız oldukça sınırlıdır, genellikle işaretlenen koşulla ilgili bazı verileri işlemeniz gerekir. Sinyal koşulları / uyanma, yarış koşulları getirmeden bunu başarmak için atomik olarak yapılmalıdır veya aşırı derecede karmaşık olmalıdır

pthreads, oldukça teknik nedenlerden dolayı, sahte bir uyandırma da sağlayabilir . Bu, bir yüklemi kontrol etmeniz gerektiği anlamına gelir, böylece durumun gerçekten belirtildiğinden emin olabilirsiniz - ve bunu sahte bir uyanmadan ayırt edebilirsiniz. Beklemeye ilişkin böyle bir durumun kontrol edilmesi gerekir - bu nedenle bir koşul değişkeni, bu durumu koruyan bir muteksi kilitlerken / kilidini açarken atomik olarak beklemek / uyanmak için bir yola ihtiyaç duyar.

Bazı verilerin üretildiğini bildirdiğiniz basit bir örneği düşünün. Belki başka bir iş parçacığı istediğiniz bazı verileri yaptı ve bu verilere bir işaretçi ayarladı.

'Some_data' işaretçisi aracılığıyla başka bir tüketici iş parçacığına bazı veriler veren bir üretici iş parçacığını düşünün.

while(1) {
    pthread_cond_wait(&cond); //imagine cond_wait did not have a mutex
    char *data = some_data;
    some_data = NULL;
    handle(data);
}

doğal olarak çok fazla yarış durumu elde edersiniz, ya diğer iplik uyandıktan some_data = new_datahemen sonra yaptıysa , ama yapmadan öncedata = some_data

Bu davayı korumak için gerçekten kendi muteksinizi yaratamazsınız.

while(1) {

    pthread_cond_wait(&cond); //imagine cond_wait did not have a mutex
    pthread_mutex_lock(&mutex);
    char *data = some_data;
    some_data = NULL;
    pthread_mutex_unlock(&mutex);
    handle(data);
}

Çalışmayacak, muteksi uyandırmak ve kapmak arasında hala bir yarış durumu şansı var. Muteksi pthread_cond_wait'ten önce yerleştirmek size yardımcı olmaz, çünkü artık beklerken muteksi tutacaksınız - yani üretici asla muteksi yakalayamayacaktır. (bu durumda, yaptığınız üreticiyi işaret etmek için ikinci bir koşul değişkeni oluşturabilirsiniz some_data- bu özellikle karmaşıklaşacaktır, özellikle de birçok üretici / tüketici istiyorsanız.)

Bu nedenle, durumdan beklerken / uyanırken muteksi atomik olarak serbest bırakma / yakalama yoluna ihtiyacınız vardır. Pthread koşulu değişkenleri bunu yapar ve işte yapmanız gerekenler:

while(1) {
    pthread_mutex_lock(&mutex);
    while(some_data == NULL) { // predicate to acccount for spurious wakeups,would also 
                               // make it robust if there were several consumers
       pthread_cond_wait(&cond,&mutex); //atomically lock/unlock mutex
    }

    char *data = some_data;
    some_data = NULL;
    pthread_mutex_unlock(&mutex);
    handle(data);
}

(üreticinin doğal olarak aynı önlemleri alması, her zaman aynı muteksle 'some_data'yı koruması ve some_data şu anda some_data'nın üzerine yazmadığından emin olması gerekir! = NULL)


while (some_data != NULL)En az bir kez koşul değişkenini beklemesi için bir do-while döngüsü olmamalı mı ?
Yargıç Maygarden

3
Hayır. Gerçekten beklediğiniz şey, 'some_data' değerinin boş olmamasıdır. "İlk seferinde" boş değilse, muteksi tutarsınız ve verileri güvenle kullanabilirsiniz. Bir do / while döngüsüne sahip olsaydınız, biri beklemeden önce koşul değişkenini işaretlerse bildirimi kaçırırsınız (birisi onları beklemeden sinyal verilen win32'de bulunan olaylar gibi değil)
nos

4
Sadece bu soru üzerinde tökezledim ve açıkçası, doğru olan bu cevabın, belirli kusurları olan paxdiablo'nun cevabından çok daha az puana sahip olduğunu bulmak gariptir (atomisite hala gereklidir, muteksin sadece durumu ele almak için gereklidir, taşıma veya bildirim için değil). Ben stackoverflow böyle çalışır ...
stefaanv

@stefaanv, kusurları detaylandırmak istiyorsanız, cevabımın yorumları olarak, bu yüzden onları aylar yerine zamanında görüyorum :-), bunları düzeltmekten memnuniyet duyarım. Kısa ifadeleriniz bana söylemeye çalıştığınız şeyi çözmek için yeterince ayrıntı vermiyor.
paxdiablo

1
@nos, olmamalıdır while(some_data != NULL)olmak while(some_data == NULL)?
Eric Z

30

POSIX koşul değişkenleri durumsuzdur. Devleti korumak sizin sorumluluğunuzdadır. Duruma hem bekleyen iş parçacıkları hem de diğer iş parçacıklarının beklemeyi durdurmalarını söyleyen iş parçacıkları erişeceğinden, bir muteks tarafından korunmalıdır. Koşul değişkenlerini muteks olmadan kullanabileceğinizi düşünüyorsanız, koşul değişkenlerinin vatansız olduğunu anlamadınız.

Koşul değişkenleri bir koşul etrafında oluşturulur. Koşul değişkeni için bekleyen iş parçacıkları bir koşul bekliyor. Sinyal koşulu değişkenlerinin bu durumu değiştirdiği konular. Örneğin, bir iş parçacığı bazı verilerin gelmesini bekliyor olabilir. Başka bir ileti dizisi verinin geldiğini fark edebilir. "Veri geldi" koşulu.

İşte basitleştirilmiş bir koşul değişkeninin klasik kullanımı:

while(1)
{
    pthread_mutex_lock(&work_mutex);

    while (work_queue_empty())       // wait for work
       pthread_cond_wait(&work_cv, &work_mutex);

    work = get_work_from_queue();    // get work

    pthread_mutex_unlock(&work_mutex);

    do_work(work);                   // do that work
}

İpliğin iş için nasıl beklediğini görün. İş bir muteks tarafından korunur. Bekleme muteks'i serbest bırakır, böylece başka bir iş parçacığı bu iş parçacığına biraz iş verebilir. Nasıl sinyal verileceği aşağıda açıklanmıştır:

void AssignWork(WorkItem work)
{
    pthread_mutex_lock(&work_mutex);

    add_work_to_queue(work);           // put work item on queue

    pthread_cond_signal(&work_cv);     // wake worker thread

    pthread_mutex_unlock(&work_mutex);
}

Çalışma kuyruğunu korumak için mutekse ihtiyacınız olduğuna dikkat edin . Koşul değişkeninin kendisinin iş olup olmadığını bilmediğine dikkat edin. Bu bir koşul değişkeni olduğunu gerekir koşul kodunuz tarafından muhafaza edilmesi gerektiğini, bir koşulu ile ilişkili ve bu parçacıkları arasında paylaşılan beri, bir muteks ile korunmalıdır.


1
Ya da, daha kısaca söylemek gerekirse, koşul değişkenlerinin tamamı atomik bir "kilit aç ve bekle" işlemi sağlamaktır. Muteks olmasaydı, kilidini açacak bir şey olmazdı.
David Schwartz

Vatansızların anlamını açıklar mısın?
snr

@snr Hiçbir devletleri yok. Bunlar "kilitli" veya "sinyalli" veya "işaretsiz" değildir. Bu nedenle, koşul değişkeni ile ilişkili herhangi bir durumu takip etmek sizin sorumluluğunuzdadır. Örneğin, koşul değişkeni bir iş parçacığının bir kuyruk boş olmadığında bunu bildirmesine izin veriyorsa, bir iş parçacığının kuyruğu boş bırakabilmesi ve diğer bazı iş parçacığının kuyruğun ne zaman boş kalmayacağını bilmesi gerekir. Bu paylaşılan bir durumdur ve muteks ile korumalısınız. Koşul değişkenini, muteks tarafından korunan bu paylaşılan durumla ilişkili olarak uyandırma mekanizması olarak kullanabilirsiniz.
David Schwartz

16

Tüm koşul değişkeni işlevleri bir muteks gerektirmez: yalnızca bekleme işlemleri gerekir. Sinyal ve yayın işlemleri muteks gerektirmez. Bir koşul değişkeni ayrıca belirli bir muteks ile kalıcı olarak ilişkili değildir; harici muteks koşul değişkenini korumaz. Bir koşul değişkeni, bekleyen iş parçacığı kuyruğu gibi dahili bir duruma sahipse, bunun koşul değişkeni içindeki dahili bir kilitle korunması gerekir.

Bekleme işlemleri bir koşul değişkeni ile muteksi bir araya getirir, çünkü:

  • bir iş parçacığı muteksi kilitledi, paylaşılan değişkenler üzerinde bazı ifadeleri değerlendirdi ve beklemesi gerektiği şekilde yanlış olduğunu buldu.
  • iş parçacığı , muteks sahibi olmaktan koşulu beklemeye atomik olarak geçmelidir .

Bu nedenle, bekleme işlemi hem muteksi hem de koşulu bağımsız değişken olarak alır: böylece bir iş parçacığının muteks sahibi olmaktan beklemeye atomik aktarımını yönetebilir, böylece iş parçacığı kayıp uyandırma yarışı durumuna kurban gitmez .

Bir iş parçacığı muteksten vazgeçerse ve ardından durumsuz bir senkronizasyon nesnesini bekler, ancak atomik olmayan bir şekilde beklerse, bir uyandırma yarışı koşulu oluşur: iş parçacığının artık kilidine sahip olmadığı ve henüz nesnenin üzerinde beklemeye başlamamıştır. Bu pencere sırasında başka bir evre girebilir, beklenen koşulu doğru yapabilir, durum bilgisi olmayan senkronizasyonu işaret edebilir ve sonra kaybolabilir. Vatansız nesne, sinyal verildiğini hatırlamaz (vatansızdır). Böylece orijinal iş parçacığı durumsuz senkronizasyon nesnesinde uykuya geçer ve ihtiyacı olan durum zaten gerçekleşmiş olsa bile uyanmaz: kayıp uyandırma.

Koşul değişkeni bekleme işlevleri, çağrı iş parçacığının muteksi bırakmadan önce uyandırmayı güvenilir bir şekilde yakalamak için kaydedildiğinden emin olarak kaybolan uyanmayı önler. Koşul değişkeni bekleme işlevi muteksi bağımsız değişken olarak almadıysa bu mümkün olmaz.


Yayın işlemlerinin muteksi edinmesini gerektirmediği konusunda referans verebilir misiniz? MSVC'de yayın yoksayılır.
xvan

@xvan POSIX pthread_cond_broadcastve pthread_cond_signaloperasyonlar (bu SO sorusunun söz konusu olduğu) muteksi bağımsız değişken olarak ele almaz; sadece durum. POSIX spesifikasyonu burada . Muteks sadece uyandıklarında bekleyen evrelerde neler olduğu ile ilgili olarak belirtilir.
Kaz

Vatansızların anlamını açıklar mısın?
snr

1
@snr Durum bilgisi olmayan bir senkronizasyon nesnesi, sinyalleşme ile ilgili herhangi bir durumu hatırlamaz. Sinyal verildiğinde, şimdi bir şey bekliyorsa, uyandırılır, aksi halde uyanma unutulur. Koşul değişkenleri durumsuzdur. Senkronizasyonu güvenilir kılmak için gerekli durum, uygulama tarafından korunur ve doğru yazılan mantığa göre, durum değişkenleriyle birlikte kullanılan muteks tarafından korunur.
Kaz

7

Diğer cevapları bu sayfa kadar özlü ve okunaklı bulmuyorum . Normalde bekleme kodu şuna benzer:

mutex.lock()
while(!check())
    condition.wait()
mutex.unlock()

Muteksi içine sarmanın üç nedeni vardır wait():

  1. mutex olmadan başka bir iş parçacığı daha signal()önce olabilir wait()ve biz bu uyanmak özledim.
  2. normalde check()başka bir iş parçacığındaki değişikliğe bağlıdır, bu yüzden yine de üzerinde karşılıklı dışlamaya ihtiyacınız vardır.
  3. en yüksek öncelikli iş parçacığının önce ilerlemesini sağlamak için (muteks kuyruğu, zamanlayıcının sırada kimlerin olacağına karar vermesine izin verir).

Üçüncü nokta her zaman bir endişe değildir - tarihsel bağlam makaleden bu sohbete bağlanır .

Bu mekanizma ile ilgili genellikle sahte uyanmalardan bahsedilir (yani bekleyen iplik signal()çağrılmadan uyandırılır ). Ancak, bu tür olaylar ilmekli tarafından ele alınır check().


4

Koşul değişkenleri bir muteks ile ilişkilidir, çünkü kaçınmak için tasarlandığı ırktan kaçınmanın tek yolu budur.

// incorrect usage:
// thread 1:
while (notDone) {
    pthread_mutex_lock(&mutex);
    bool ready = protectedReadyToRunVariable
    pthread_mutex_unlock(&mutex);
    if (ready) {
        doWork();
    } else {
        pthread_cond_wait(&cond1); // invalid syntax: this SHOULD have a mutex
    }
}

// signalling thread
// thread 2:
prepareToRunThread1();
pthread_mutex_lock(&mutex);
   protectedReadyToRuNVariable = true;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond1);

Now, lets look at a particularly nasty interleaving of these operations

pthread_mutex_lock(&mutex);
bool ready = protectedReadyToRunVariable;
pthread_mutex_unlock(&mutex);
                                 pthread_mutex_lock(&mutex);
                                 protectedReadyToRuNVariable = true;
                                 pthread_mutex_unlock(&mutex);
                                 pthread_cond_signal(&cond1);
if (ready) {
pthread_cond_wait(&cond1); // uh o!

Bu noktada, koşul değişkenini işaret edecek bir iplik yoktur, bu nedenle korunanReadyToRunVariable gitmeye hazır olduğunu söylese de thread1 sonsuza kadar bekleyecektir!

Bunun tek yolu koşul değişkenlerinin muteksi atomik olarak serbest bırakması ve aynı zamanda koşul değişkenini beklemeye başlamasıdır. Bu nedenle cond_wait işlevi bir muteks gerektirir

// correct usage:
// thread 1:
while (notDone) {
    pthread_mutex_lock(&mutex);
    bool ready = protectedReadyToRunVariable
    if (ready) {
        pthread_mutex_unlock(&mutex);
        doWork();
    } else {
        pthread_cond_wait(&mutex, &cond1);
    }
}

// signalling thread
// thread 2:
prepareToRunThread1();
pthread_mutex_lock(&mutex);
   protectedReadyToRuNVariable = true;
   pthread_cond_signal(&mutex, &cond1);
pthread_mutex_unlock(&mutex);

3

Aradığınızda muteksin kilitli olması gerekir pthread_cond_wait; atom olarak adlandırdığınızda, hem muteksin kilidini açar hem de koşulu engeller. Durum bildirildikten sonra, atomik olarak tekrar kilitler ve geri döner.

Bu, istenirse öngörülebilir zamanlamanın uygulanmasına izin verir, çünkü sinyalleme yapacak olan iş parçacığı, muteksin işlenmesi için serbest bırakılıncaya kadar bekleyebilir ve ardından durumu işaret edebilir.


Yani ... muteks'in her zaman açık kalmasını değil , beklemeden hemen önce kilitlemem ve sonra bitirdikten hemen sonra kilidini açmamın bir nedeni var mı?
ELLIOTTCABLE

Muteks ayrıca bekleme ve sinyal verme iplikleri arasındaki bazı potansiyel yarışları da çözer. durumu değiştirirken ve sinyal verirken muteks her zaman kilitli olduğu sürece, kendinizi asla sinyali kaçırdığınızı ve sonsuza kadar uyuduğunuzu
göremezsiniz

Yani ... gerektiğini ilk beklemek on Muteksleri conditionvar en mutex, conditionvar bekleyen önce? Hiç anladığımdan emin değilim.
ELLIOTTCABLE

2
@elliottcable: Muteksi tutmadan beklemeniz gerekip gerekmediğini nasıl bilebilirsiniz? İçin Ne bekliyoruz ne olur sadece oldu?
David Schwartz

1

Koşul değişkeninin gerçek bir örneğini istiyorsanız sınıfta bir alıştırma yaptım:

#include "stdio.h"
#include "stdlib.h"
#include "pthread.h"
#include "unistd.h"

int compteur = 0;
pthread_cond_t varCond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex_compteur;

void attenteSeuil(arg)
{
    pthread_mutex_lock(&mutex_compteur);
        while(compteur < 10)
        {
            printf("Compteur : %d<10 so i am waiting...\n", compteur);
            pthread_cond_wait(&varCond, &mutex_compteur);
        }
        printf("I waited nicely and now the compteur = %d\n", compteur);
    pthread_mutex_unlock(&mutex_compteur);
    pthread_exit(NULL);
}

void incrementCompteur(arg)
{
    while(1)
    {
        pthread_mutex_lock(&mutex_compteur);

            if(compteur == 10)
            {
                printf("Compteur = 10\n");
                pthread_cond_signal(&varCond);
                pthread_mutex_unlock(&mutex_compteur);
                pthread_exit(NULL);
            }
            else
            {
                printf("Compteur ++\n");
                compteur++;
            }

        pthread_mutex_unlock(&mutex_compteur);
    }
}

int main(int argc, char const *argv[])
{
    int i;
    pthread_t threads[2];

    pthread_mutex_init(&mutex_compteur, NULL);

    pthread_create(&threads[0], NULL, incrementCompteur, NULL);
    pthread_create(&threads[1], NULL, attenteSeuil, NULL);

    pthread_exit(NULL);
}

1

Kavramsal bir ihtiyaçtan ziyade özel bir tasarım kararı gibi görünüyor.

Pthreads belgelerine göre muteksin ayrılmamasının nedeni, onları birleştirerek önemli bir performans iyileştirmesi olmasıdır ve bir muteks kullanmıyorsanız ortak yarış koşulları nedeniyle neredeyse her zaman yapılacaktır.

https://linux.die.net/man/3/pthread_cond_wait

Mutekslerin Özellikleri ve Koşul Değişkenleri

Muteks ediniminin ve salıverilmesinin durum beklemesinden ayrılması önerildi. Bu reddedildi, çünkü gerçekte gerçek zamanlı uygulamaları kolaylaştıran operasyonun birleşik doğasıdır. Bu uygulamalar, yüksek öncelikli bir iş parçacığını, koşul değişkeni ile muteks arasında arayan için saydam bir şekilde atomik olarak hareket ettirebilir. Bu, fazladan bağlamsal anahtarları önleyebilir ve bekleyen iş parçacığı sinyali verildiğinde muteksin daha belirleyici bir şekilde elde edilmesini sağlayabilir. Böylece, adalet ve öncelikli konular doğrudan planlama disiplini ile ele alınabilir. Ayrıca, mevcut durum bekleme işlemi mevcut uygulama ile eşleşir.


0

Bununla ilgili tonlarca tefsir var, ancak bunu bir örnekle özetlemek istiyorum.

1 void thr_child() {
2    done = 1;
3    pthread_cond_signal(&c);
4 }

5 void thr_parent() {
6    if (done == 0)
7        pthread_cond_wait(&c);
8 }

Kod pasajındaki sorun nedir? Devam etmeden önce biraz düşünün.


Sorun gerçekten incedir. Ebeveyn çağırır thr_parent()ve sonra değerini araştırırsa done, bunun olduğunu görür 0ve böylece uyumaya çalışır. Ancak, uykuya dalmak için beklemeden hemen önce, ebeveyn 6-7 satırları arasında kesilir ve çocuk koşar. Çocuk devlet değişkeni değiştirir doneiçin 1ve sinyalleri, ancak hiçbir iplik bekliyor ve böylece hiçbir iplik uyandırılır. Ebeveyn tekrar koştuğunda, sonsuza kadar uyur, bu da gerçekten berbattır.

Ya kilitler ayrı ayrı yapılırken yapılırsa?

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.