CodeGym /Java Blogu /Rastgele /Mutex, Monitor ve Semaphore Arasındaki Fark
John Squirrels
Seviye
San Francisco

Mutex, Monitor ve Semaphore Arasındaki Fark

grupta yayınlandı
MERHABA! CodeGym'de multithreading çalışırken sık sık "mutex" ve "monitor" kavramlarıyla karşılaştınız. Göz atmadan, nasıl farklı olduklarını söyleyebilir misiniz? :) Evet ise, aferin! Değilse (bu en yaygın olanıdır), bu hiç de şaşırtıcı değil. "Mutex" ve "monitör" aslında birbiriyle ilişkili kavramlardır. Ek olarak, diğer web sitelerinde çoklu okuma ile ilgili dersler okuduğunuzda ve videolar izlediğinizde, buna benzer başka bir kavramla karşılaşacaksınız: "semafor". Ayrıca monitörlere ve mutekslere çok benzer bir işleve sahiptir. Bu yüzden bu üç terimi inceleyeceğiz. Birkaç örneğe bakacağız ve bu kavramların birbirinden ne kadar farklı olduğuna dair kesin bir anlayışa geleceğiz :)

muteks

Bir muteks (veya kilit), iş parçacıklarını senkronize etmek için özel bir mekanizmadır. Biri Java'daki her nesneye "eklenir" — bunu zaten biliyorsunuz :) Standart sınıflar kullanmanız veya kendi sınıflarınızı oluşturmanız, örneğin Cat ve Dog fark etmez : tüm sınıfların tüm nesnelerinin bir muteksi vardır . "Mutex" terimi, amacını mükemmel bir şekilde tanımlayan "MUTual EXclusion" kelimesinden gelmektedir. Daha önceki derslerimizden birinde söylediğimiz gibi, bir muteks, nesneye aynı anda yalnızca bir iş parçacığının erişmesini sağlamayı mümkün kılar. Bir muteksin popüler bir gerçek hayat örneği tuvaletleri içerir. Bir kişi bir tuvalet bölmesine girdiğinde kapıyı içeriden kilitler. Tuvalet, birden fazla iş parçacığı tarafından erişilebilen bir nesne gibidir. Bölme kapısındaki kilit bir muteks gibidir ve dışarıdaki insan sırası iplikleri temsil eder. Kapıdaki kilit tuvaletin muteksidir: İçeriye sadece bir kişinin girmesini sağlar. Mutex, monitör ve semafor arasındaki fark nedir?  - 2Başka bir deyişle, paylaşılan kaynaklarla aynı anda yalnızca bir iş parçacığı çalışabilir. Diğer ileti dizilerinin (kişilerin) işgal edilen kaynaklara erişme girişimleri başarısız olur. Bir muteksin birkaç önemli özelliği vardır. İlk olarak , yalnızca iki durum mümkündür: "kilidi açık" ve "kilitli". Bu, nasıl çalıştığını anlamamıza yardımcı olur: Boole değişkenleriyle (doğru/yanlış) veya ikili sayılarla (0/1) paralellikler çizebilirsiniz. , durum doğrudan kontrol edilemez. Java, bir nesneyi açıkça almanıza, muteksini almanıza ve istenen durumu atamanıza izin verecek bir mekanizmaya sahip değildir. Başka bir deyişle, şöyle bir şey yapamazsınız:

Object myObject = new Object();
Mutex mutex = myObject.getMutex();
mutex.free();
Bu, bir nesnenin muteksini serbest bırakamayacağınız anlamına gelir. Yalnızca Java makinesinin ona doğrudan erişimi vardır. Programcılar, dilin araçları aracılığıyla mutekslerle çalışır.

monitör

Bir monitör, bir muteks üzerinde ek bir "üst yapıdır". Aslında monitör, programcı için "görünmez" olan bir kod yığınıdır. Daha önce mutekslerden bahsederken basit bir örnek vermiştik:

public class Main {

   private Object obj = new Object();

   public void doSomething() {

       // ...some logic, available for all threads

       synchronized (obj) {

           // Logic available to just one thread at a time
       }
   }
}
synchronized anahtar sözcüğü ile işaretlenen kod bloğunda obj nesnemizin muteksi alınır. Harika, kilidi alabiliriz, ancak "koruma" tam olarak nasıl sağlanır? Syncized kelimesini gördüğümüzde , diğer iş parçacıklarının bloğa girmesini engelleyen nedir? Koruma bir monitörden geliyor! Derleyici, synchronized anahtar sözcüğünü birkaç özel kod parçasına dönüştürür. Yine doSomething() metodu ile örneğimize dönelim . Buna ekleyeceğiz:

public class Main {

   private Object obj = new Object();

   public void doSomething() {

       // ...some logic, available for all threads

       // Logic available to just one thread at a time
       synchronized (obj) {

           /* Do important work that requires that the object
           be accessed by only one thread */
           obj.someImportantMethod();
       }
   }
}
Derleyici bu kodu dönüştürdükten sonra "başlık altında" olan şey şudur:

public class Main {

   private Object obj = new Object();

   public void doSomething() throws InterruptedException {

       // ...some logic, available for all threads

       // Logic available to just one thread at a time:
     
       /* as long as the object's mutex is busy,
       all the other threads (except the one that acquired it) are put to sleep */
       while (obj.getMutex().isBusy()) {
           Thread.sleep(1);
       }

       // Mark the object's mutex as busy
       obj.getMutex().isBusy() = true;

       /* Do important work that requires that the object
       be accessed by only one thread */
       obj.someImportantMethod();

       // Free the object's mutex
       obj.getMutex().isBusy() = false;
   }
}
Elbette bu gerçek bir örnek değil. Burada, Java makinesinin içinde neler olduğunu tasvir etmek için Java benzeri kod kullandık. Bununla birlikte, bu sözde kod, senkronize edilmiş blok içindeki nesne ve iş parçacıklarında gerçekte ne olduğu ve derleyicinin bu anahtar kelimeyi programcı için "görünmez" olan çeşitli ifadelere nasıl dönüştürdüğü hakkında mükemmel bir anlayış sağlar. Temel olarak Java, bir monitörü temsil etmek için synchronized anahtar sözcüğünü kullanır . Son örnekte synchronized anahtar sözcüğü yerine görünen tüm kod monitördür.

Semafor

Kişisel çoklu okuma çalışmanızda karşılaşacağınız başka bir kelime de "semafor" dur. Bunun ne olduğunu ve monitör ve muteksten nasıl farklı olduğunu görelim. Semafor, bazı kaynaklara erişimi senkronize etmek için kullanılan bir araçtır. Ayırt edici özelliği, senkronizasyon mekanizmasını oluşturmak için bir sayaç kullanmasıdır. Sayaç, paylaşılan kaynağa aynı anda kaç iş parçacığının erişebileceğini söyler. Mutex, monitör ve semafor arasındaki fark nedir?  - 3Java'daki semaforlar, Semafor sınıfı tarafından temsil edilir. Semafor nesneleri oluştururken aşağıdaki yapıcıları kullanabiliriz:

Semaphore(int permits)
Semaphore(int permits, boolean fair)
Aşağıdakileri yapıcıya iletiyoruz:
    int izin verir — sayacın başlangıç ​​ve maksimum değeri. Başka bir deyişle, bu parametre paylaşılan kaynağa aynı anda kaç iş parçacığının erişebileceğini belirler;
  • boolean fair — ileti dizilerinin erişeceği sırayı belirler. adil doğruysa, bekleyen ileti dizilerine talep ettikleri sırayla erişim izni verilir. Yanlış ise, sıra iş parçacığı zamanlayıcısı tarafından belirlenir.
Semafor kullanımının klasik bir örneği, yemek filozofu problemidir. Mutex, monitör ve semafor arasındaki fark nedir?  - 4Anlamayı kolaylaştırmak için biraz basitleştireceğiz. Öğle yemeği yemesi gereken 5 filozofumuz olduğunu hayal edin. Ek olarak, aynı anda en fazla iki kişinin konaklayabileceği bir masamız var. Görevimiz tüm filozofları beslemektir. Hiçbiri aç kalmamalı ve masaya oturmaya çalışırken hiçbiri birbirini "engellememeli" (çıkmazdan kaçınmalıyız). İşte filozof sınıfımızın nasıl görüneceği:

class Philosopher extends Thread {

   private Semaphore sem;

   // Did the philosopher eat?
   private boolean full = false;

   private String name;

   Philosopher(Semaphore sem, String name) {
       this.sem=sem;
       this.name=name;
   }

   public void run()
   {
       try
       {
           // If the philosopher has not eaten
           if (!full) {
               // Ask the semaphore for permission to run
               sem.acquire();
               System.out.println(name + " takes a seat at the table");

               // The philosopher eats
               sleep(300);
               full = true;

               System.out.println(name + " has eaten! He leaves the table");
               sem.release();

               // The philosopher leaves, making room for others
               sleep(300);
           }
       }
       catch(InterruptedException e) {
           System.out.println("Something went wrong!");
       }
   }
}
Ve işte programımızı çalıştıracak kod:

public class Main {

   public static void main(String[] args) {

       Semaphore sem = new Semaphore(2);
       new Philosopher(sem, "Socrates").start();
       new Philosopher(sem,"Plato").start();
       new Philosopher(sem,"Aristotle").start();
       new Philosopher(sem, "Thales").start();
       new Philosopher(sem, "Pythagoras").start();
   }
}
Şu koşulu yerine getirmek için sayacı 2'ye ayarlanmış bir semafor yarattık: aynı anda sadece iki filozof yemek yiyebilir. Yani, Philosopher sınıfımız Thread'i miras aldığı için aynı anda yalnızca iki thread çalışabilir ! Semaphore sınıfının Acquire () ve Release() yöntemleri, erişim sayacını kontrol eder. Acquire() yöntemi, semafordan kaynağa erişmesini ister. Sayaç >0 ise, erişim verilir ve sayaç 1 azaltılır. Release ()yöntem önceden verilen erişimi "serbest bırakır" ve onu sayaca geri döndürür (semaforun erişim sayacını 1 artırır). Programı çalıştırdığımızda ne elde ederiz? Sorun çözüldü mü? Filozoflarımız sıralarını beklerken savaşmayacaklar mı? :) İşte elimizdeki konsol çıktısı:

Socrates takes a seat at the table 
Plato takes a seat at the table 
Socrates has eaten! He leaves the table 
Plato has eaten! He leaves the table 
Aristotle takes a seat at the table 
Pythagoras takes a seat at the table 
Aristotle has eaten! He leaves the table 
Pythagoras has eaten! He leaves the table 
Thales takes a seat at the table 
Thales has eaten! He leaves the table 
Yaptık! Ve Thales tek başına yemek yemek zorunda kalsa da onu gücendirdiğimizi düşünmüyorum :) Bir muteks ile semafor arasında bazı benzerlikler fark etmiş olabilirsiniz. Aslında, aynı misyona sahipler: bazı kaynaklara erişimi senkronize etmek. Mutex, monitör ve semafor arasındaki fark nedir?  - 5Tek fark, bir nesnenin muteksinin aynı anda yalnızca bir iş parçacığı tarafından elde edilebilmesidir, oysa bir iş parçacığı sayacı kullanan bir semafor durumunda, birkaç iş parçacığı kaynağa aynı anda erişebilir. Bu sadece bir tesadüf değil :) Bir muteks aslında bir semafordur1 sayısı ile. Diğer bir deyişle, tek bir iş parçacığını barındırabilen bir semafordur. "İkili semafor" olarak da bilinir, çünkü sayacı yalnızca 2 değere sahip olabilir - 1 ("kilidi açık") ve 0 ("kilitli"). Bu kadar! Gördüğünüz gibi, o kadar da kafa karıştırıcı değil :) Şimdi, multithreading'i internette daha ayrıntılı incelemek istiyorsanız, bu kavramlarda gezinmeniz biraz daha kolay olacaktır. Sonraki derslerde görüşmek üzere!
Yorumlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION