CodeGym /Blog Java /rawak /Perbezaan Antara Mutex, Monitor dan Semaphore
John Squirrels
Tahap
San Francisco

Perbezaan Antara Mutex, Monitor dan Semaphore

Diterbitkan dalam kumpulan
Hai! Apabila anda belajar multithreading di CodeGym, anda sering menemui konsep "mutex" dan "monitor". Tanpa mengintip, bolehkah anda katakan bagaimana mereka berbeza? :) Jika ya, syabas! Jika tidak (ini adalah yang paling biasa), itu tidak mengejutkan. "Mutex" dan "monitor" sebenarnya adalah konsep yang berkaitan. Selain itu, apabila anda membaca pelajaran dan menonton video tentang multithreading di tapak web lain, anda akan menemui satu lagi konsep yang serupa: "semaphore". Ia juga mempunyai fungsi yang hampir sama dengan monitor dan mutex. Itulah sebabnya kami akan menyiasat tiga penggal ini. Kami akan melihat beberapa contoh dan mendapat pemahaman yang pasti tentang bagaimana konsep ini berbeza antara satu sama lain :)

Mutex

Mutex (atau kunci) ialah mekanisme khas untuk menyegerakkan benang. Satu "dilampirkan" pada setiap objek dalam Java — anda sudah tahu itu :) Tidak kira jika anda menggunakan kelas standard atau mencipta kelas anda sendiri, contohnya Cat dan Dog : semua objek dari semua kelas mempunyai mutex . Istilah "mutex" berasal daripada "MUTual EXclusion", yang menerangkan tujuannya dengan sempurna. Seperti yang kami katakan dalam salah satu pelajaran kami sebelum ini, mutex memungkinkan untuk memastikan bahawa hanya satu utas pada satu masa mempunyai akses kepada objek. Contoh sebenar mutex yang popular melibatkan tandas. Apabila seseorang memasuki sekatan tandas, dia mengunci pintu dari dalam. Tandas adalah seperti objek yang boleh diakses oleh pelbagai benang. Kunci pada pintu sekatan adalah seperti mutex, dan barisan orang di luar mewakili benang. Kunci pada pintu adalah mutex tandas: ia memastikan bahawa hanya satu orang boleh masuk ke dalam. Apakah perbezaan antara mutex, monitor dan semaphore?  - 2Dalam erti kata lain, hanya satu urutan pada satu masa boleh berfungsi dengan sumber yang dikongsi. Percubaan oleh rangkaian lain (orang) untuk mendapatkan akses kepada sumber yang diduduki akan gagal. Mutex mempunyai beberapa ciri penting. Pertama , hanya dua keadaan yang mungkin: "dikunci" dan "dikunci". Ini membantu kami memahami cara ia berfungsi: anda boleh melukis selari dengan pembolehubah Boolean (benar/salah) atau nombor perduaan (0/1). , negeri tidak boleh dikawal secara langsung. Java tidak mempunyai mekanisme yang membenarkan anda mengambil objek secara eksplisit, mendapatkan mutexnya, dan menetapkan status yang dikehendaki. Dengan kata lain, anda tidak boleh melakukan sesuatu seperti:

Object myObject = new Object();
Mutex mutex = myObject.getMutex();
mutex.free();
Ini bermakna anda tidak boleh melepaskan mutex objek. Hanya mesin Java yang mempunyai akses terus kepadanya. Pengaturcara bekerja dengan mutex melalui alat bahasa.

Pantau

Monitor ialah "superstructure" tambahan di atas mutex. Malah, monitor ialah sekeping kod yang "tidak kelihatan" kepada pengaturcara. Apabila kami bercakap tentang mutex sebelum ini, kami memberikan contoh mudah:

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
       }
   }
}
Dalam blok kod yang ditandakan dengan kata kunci disegerakkan , mutex objek obj kami diperoleh. Hebat, kita boleh memperoleh kunci itu, tetapi bagaimana sebenarnya "perlindungan" yang disediakan? Apabila kita melihat perkataan disegerakkan , apakah yang menghalang urutan lain daripada memasuki blok? Perlindungan datang dari monitor! Pengkompil menukar kata kunci yang disegerakkan kepada beberapa keping kod khas. Sekali lagi, mari kita kembali kepada contoh kita dengan kaedah doSomething() . Kami akan menambahnya:

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();
       }
   }
}
Inilah yang berlaku "di bawah hud" selepas pengkompil menukar kod ini:

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;
   }
}
Sudah tentu, ini bukan contoh sebenar. Di sini, kami menggunakan kod seperti Java untuk menggambarkan apa yang berlaku di dalam mesin Java. Walau bagaimanapun, kod pseudo ini memberikan pemahaman yang sangat baik tentang apa yang sebenarnya berlaku dengan objek dan benang di dalam blok yang disegerakkan dan bagaimana pengkompil menukar kata kunci ini kepada beberapa pernyataan yang "tidak kelihatan" kepada pengaturcara. Pada asasnya, Java menggunakan kata kunci yang disegerakkan untuk mewakili monitor . Semua kod yang muncul dan bukannya kata kunci yang disegerakkan dalam contoh terakhir ialah monitor.

Semafor

Satu lagi perkataan yang anda akan temui dalam kajian peribadi anda tentang multithreading ialah "semaphore". Mari kita fikirkan apakah ini dan bagaimana ia berbeza daripada monitor dan mutex. Semaphore ialah alat untuk menyegerakkan akses kepada beberapa sumber. Ciri tersendirinya ialah ia menggunakan kaunter untuk mencipta mekanisme penyegerakan. Kaunter memberitahu kami berapa banyak utas boleh mengakses sumber yang dikongsi secara serentak. Apakah perbezaan antara mutex, monitor dan semaphore?  - 3Semaphore di Jawa diwakili oleh kelas Semaphore . Apabila mencipta objek semaphore, kita boleh menggunakan pembina berikut:

Semaphore(int permits)
Semaphore(int permits, boolean fair)
Kami menyampaikan yang berikut kepada pembina:
    int permit — nilai awal dan maksimum kaunter. Dalam erti kata lain, parameter ini menentukan bilangan utas yang boleh mengakses sumber yang dikongsi secara serentak;
  • boolean fair — menetapkan susunan urutan benang akan mendapat akses. Jika adil adalah benar, maka akses diberikan kepada urutan menunggu dalam susunan yang mereka memintanya. Jika ia palsu, maka susunan ditentukan oleh penjadual benang.
Contoh klasik penggunaan semaphore ialah masalah ahli falsafah makan. Apakah perbezaan antara mutex, monitor dan semaphore?  - 4Untuk memudahkan pemahaman, kami permudahkan sedikit. Bayangkan kita ada 5 ahli falsafah yang perlu makan tengah hari. Selain itu, kami mempunyai satu meja yang boleh memuatkan tidak lebih daripada dua orang secara serentak. Tugas kita ialah memberi makan kepada semua ahli falsafah. Tiada seorang pun daripada mereka harus kelaparan, dan tiada seorang pun daripada mereka harus "menghalang" satu sama lain apabila cuba duduk di meja (kita mesti mengelakkan kebuntuan). Inilah rupa kelas ahli falsafah kami:

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!");
       }
   }
}
Dan inilah kod untuk menjalankan program kami:

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();
   }
}
Kami mencipta semaphore yang kaunternya ditetapkan kepada 2 untuk memenuhi syarat: hanya dua ahli falsafah boleh makan pada masa yang sama. Iaitu, hanya dua utas boleh dijalankan pada masa yang sama, kerana kelas Ahli Falsafah kami mewarisi Thread ! Kaedah acquire () dan release() kelas Semaphore mengawal kaunter aksesnya. Kaedah acquire() meminta semaphore untuk akses kepada sumber. Jika kaunter ialah >0, maka akses diberikan dan kaunter dikurangkan sebanyak 1. Keluaran ()kaedah "melepaskan" akses yang diberikan sebelum ini, mengembalikannya ke kaunter (meningkatkan kaunter akses semaphore sebanyak 1). Apa yang kita dapat apabila kita menjalankan program? Adakah masalah selesai? Adakah ahli falsafah kita tidak akan berjuang sementara mereka menunggu giliran mereka? :) Berikut ialah output konsol yang kami dapat:

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 
Kita berjaya! Dan walaupun Thales terpaksa makan seorang diri, saya tidak fikir kami telah menyinggung perasaannya :) Anda mungkin perasan beberapa persamaan antara mutex dan semaphore. Malah, mereka mempunyai misi yang sama: untuk menyegerakkan akses kepada beberapa sumber. Apakah perbezaan antara mutex, monitor dan semaphore?  - 5Satu-satunya perbezaan ialah mutex objek boleh diperolehi oleh hanya satu utas pada satu masa, manakala dalam kes semaphore, yang menggunakan pembilang benang, beberapa utas boleh mengakses sumber secara serentak. Ini bukan sekadar kebetulan :) Mutex sebenarnya adalah semafordengan kiraan 1. Dalam erti kata lain, ia adalah semaphore yang boleh menampung satu utas. Ia juga dikenali sebagai "semaphore binari" kerana pembilangnya hanya boleh mempunyai 2 nilai — 1 ("tidak berkunci") dan 0 ("terkunci"). Itu sahaja! Seperti yang anda lihat, ia tidak begitu mengelirukan lagi :) Sekarang, jika anda ingin mempelajari multithreading dengan lebih terperinci di Internet, ia akan menjadi lebih mudah untuk anda menavigasi konsep ini. Jumpa anda dalam pelajaran seterusnya!
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION