JavaRush /Blog Java /Random-MS /Apakah perbezaan antara mutex, monitor dan semaphore

Apakah perbezaan antara mutex, monitor dan semaphore

Diterbitkan dalam kumpulan
hello! Semasa mempelajari multithreading dalam JavaRush, anda sering menjumpai konsep "mutex" dan "monitor". Bolehkah anda sekarang, tanpa mengintip, menjawab bagaimana mereka berbeza? :) Apakah perbezaan antara mutex, monitor dan semaphore - 1Jika anda boleh, syabas! Jika tidak (dan selalunya ini berlaku) - tidak hairanlah. Konsep "mutex" dan "monitor" sememangnya berkaitan. Selain itu, semasa membaca kuliah dan menonton video mengenai multithreading pada sumber luaran di Internet, anda akan menemui satu lagi konsep serupa - "semaphore". Fungsinya juga hampir sama dengan monitor dan mutex. Oleh itu, mari kita fahami ketiga-tiga istilah ini, lihat beberapa contoh dan akhirnya susun dalam kepala kita pemahaman tentang perbezaan antara satu sama lain :)

Mutex

Mutex ialah objek khas untuk menyegerakkan benang. Ia "dilampirkan" pada setiap objek dalam Java - anda sudah tahu itu :) Tidak kira sama ada anda menggunakan kelas standard atau mencipta kelas anda sendiri, katakan, Catdan Dog: semua objek semua kelas mempunyai mutex . Nama "mutex" berasal daripada bahasa Inggeris "MUTual EXclusion" - "mutual exclusion", dan ini menggambarkan dengan sempurna tujuannya. Seperti yang kami katakan dalam salah satu kuliah sebelumnya, tugas mutex adalah untuk menyediakan mekanisme sedemikian supaya hanya satu utas mempunyai akses kepada objek pada masa tertentu . Analogi popular untuk mutex dalam kehidupan sebenar ialah "contoh tandas." Apabila seseorang memasuki tandas, dia mengunci pintu dari dalam. Tandas bertindak sebagai objek yang boleh diakses oleh pelbagai benang. Kunci pada pintu tandas adalah peranan mutex, dan barisan orang di luar adalah peranan benang. Kunci pada pintu adalah mutex tandas: ia memastikan bahawa hanya satu orang boleh berada di dalam pada satu masa. Apakah perbezaan antara mutex, monitor dan semaphore - 2Dalam erti kata lain, hanya satu urutan pada satu masa boleh berfungsi pada sumber yang dikongsi. Percubaan oleh rangkaian lain (orang) untuk mengakses sumber yang diduduki akan gagal. Mutex mempunyai beberapa ciri penting. Pertama , hanya dua negeri yang boleh dilakukan - "bebas" dan "sibuk". Ini menjadikannya lebih mudah untuk memahami cara ia berfungsi: selari boleh dilukis dengan pembolehubah Boolean benar/salah atau sistem nombor binari 1/0. Kedua , negeri tidak boleh dikawal secara langsung. Tiada mekanisme dalam Java yang membolehkan anda mengambil objek secara eksplisit, mendapatkan mutexnya dan menetapkan status yang dikehendaki kepadanya. Dengan kata lain, anda tidak boleh melakukan sesuatu seperti:
Object myObject = new Object();
Mutex mutex = myObject.getMutex();
mutex.free();
Oleh itu, mutex objek tidak boleh dilepaskan. Hanya mesin Java yang mempunyai akses terus kepadanya. Pengaturcara bekerja dengan mutex menggunakan alat bahasa.

Pantau

Monitor ialah "tambahan" tambahan kepada mutex. Malah, monitor adalah sekeping kod "tidak kelihatan" kepada pengaturcara . Bercakap tentang mutex tadi, kami memberikan contoh mudah:
public class Main {

   private Object obj = new Object();

   public void doSomething() {

       //...some logic available to all threads

       synchronized (obj) {

           //logic that is only available to one thread at a time
       }
   }
}
Dalam blok kod yang ditandakan dengan perkataan synchronized, mutex objek kita ditangkap obj. Okey, penangkapan berlaku, tetapi bagaimana sebenarnya "mekanisme pertahanan" dicapai? synchronizedMengapakah utas lain tidak boleh masuk ke dalam blok apabila mereka melihat perkataan ? Ia adalah monitor yang mencipta mekanisme perlindungan! Pengkompil menukar perkataan synchronizedkepada beberapa keping kod khas. Sekali lagi mari kita kembali ke contoh kita dengan kaedah doSomething()dan tambahkannya:
public class Main {

   private Object obj = new Object();

   public void doSomething() {

       //...some logic available to all threads

       //logic that is only available to one thread at a time
       synchronized (obj) {

           /*выполнить важную работу, при которой доступ к an objectу
           должен быть только у одного потока*/
           obj.someImportantMethod();
       }
   }
}
Inilah yang akan berlaku "di bawah hud" program kami selepas pengkompil menukar kod ini:
public class Main {

   private Object obj = new Object();

   public void doSomething() throws InterruptedException {

       //...some logic available to all threads

       //логика, которая одновременно доступна только для одного потока:

       /*до тех пор, пока мьютекс an object занят -
       любой другой поток (кроме того, который его захватил), спит*/
       while (obj.getMutex().isBusy()) {
           Thread.sleep(1);
       }

       //пометить мьютекс an object How занятый
       obj.getMutex().isBusy() = true;

       /*выполнить важную работу, при которой доступ к an objectу
       должен быть только у одного потока*/
       obj.someImportantMethod();

       //освободить мьютекс an object
       obj.getMutex().isBusy() = false;
   }
}
Contohnya, sudah tentu, tidak benar. Di sini, menggunakan kod seperti Java, kami cuba mencerminkan apa yang berlaku pada masa ini di dalam mesin Java. Walau bagaimanapun, pseudokod ini memberikan pemahaman yang hebat tentang apa yang sebenarnya berlaku dengan objek dan benang di dalam blok synchronizeddan bagaimana pengkompil menukar perkataan ini kepada beberapa arahan yang "tidak kelihatan" kepada pengaturcara. Pada asasnya, monitor dalam Java dinyatakan menggunakan perkataansynchronized . Semua kod yang muncul dan bukannya perkataan synchronizeddalam contoh terakhir ialah monitor.

Semafor

Satu lagi perkataan yang anda temui semasa mempelajari multithreading sendiri ialah "semaphore". Mari kita ketahui apa itu dan bagaimana ia berbeza daripada monitor dan mutex. Semaphore ialah satu cara untuk menyegerakkan akses kepada sumber. Keanehannya ialah ia menggunakan kaunter apabila 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 kepada pembina:
  • int permits— nilai pembilang awal dan maksimum. Iaitu, berapa banyak utas boleh mengakses sumber yang dikongsi secara serentak;

  • boolean fair- untuk menetapkan susunan urutan yang akan menerima akses. Jika fair= true , akses diberikan kepada urutan menunggu dalam susunan yang mereka memintanya. Jika ia palsu , pesanan akan ditentukan oleh penjadual urutan.

Contoh klasik penggunaan semaphore ialah masalah ahli falsafah makan tengah hari .
Apakah perbezaan antara mutex, monitor dan semaphore - 4
Kami akan permudahkan sedikit syaratnya untuk pemahaman yang lebih baik. Bayangkan kita mempunyai 5 ahli falsafah yang memerlukan makan tengah hari. Pada masa yang sama, kami mempunyai satu meja, dan tidak lebih daripada dua orang boleh berada di meja itu pada masa yang sama. Tugas kami adalah memberi makan kepada semua ahli falsafah. Kedua-dua mereka tidak sepatutnya kelaparan, atau 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;

   // поел ли философ
   private boolean full = false;

   private String name;

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

   public void run()
   {
       try
       {
           // если философ еще не ел
           if (!full) {
               //Запрашиваем у семафора разрешение на выполнение
               sem.acquire();
               System.out.println (name + " садится за стол");

               // философ ест
               sleep(300);
               full = true;

               System.out.println (name + " поел! Он выходит из-за стола");
               sem.release();

               // философ ушел, освободив место другим
               sleep(300);
           }
       }
       catch(InterruptedException e) {
           System.out.println ("What-то пошло не так!");
       }
   }
}
Dan inilah kod untuk menjalankan program kami:
public class Main {

   public static void main(String[] args) {

       Semaphore sem = new Semaphore(2);
       new Philosopher(sem,"Сократ").start();
       new Philosopher(sem,"Платон").start();
       new Philosopher(sem,"Аристотель").start();
       new Philosopher(sem,"Фалес").start();
       new Philosopher(sem,"Пифагор").start();
   }
}
Kami mencipta semafor dengan kiraan 2 untuk memenuhi syarat bahawa hanya dua ahli falsafah boleh makan pada masa yang sama. Iaitu, hanya dua utas boleh berfungsi serentak, kerana kelas kami Philosopherdiwarisi daripada Thread! Kelas acquire()dan kaedah mengawal kaunter kebenarannya. Kaedah meminta kebenaran untuk mengakses sumber daripada semaphore. Jika pembilang > 0, kebenaran diberikan dan pembilang dikurangkan sebanyak 1. Kaedah "melepaskan" kebenaran yang diberikan sebelum ini dan mengembalikannya ke kaunter (menaikkan pembilang geran semaphore sebanyak 1). Apa yang kita dapat apabila kita menjalankan program? Adakah masalah telah selesai?Adakah ahli falsafah kita akan berjuang sementara menunggu giliran? :) Ini adalah output konsol yang kami terima: Socrates duduk di meja Plato duduk di meja yang Socrates telah makan! Dia meninggalkan meja. Plato sudah makan! Dia meninggalkan meja Aristotle duduk di meja Pythagoras duduk di meja Aristotle telah makan! Dia meninggalkan meja yang telah dimakan oleh Pythagoras! Dia meninggalkan meja Thales duduk di meja yang Thales makan! Dia meninggalkan meja. Kami berjaya! Dan walaupun Thales terpaksa makan seorang diri, saya rasa dia tidak marah kepada kami :) Anda mungkin perasan beberapa persamaan antara mutex dan semaphore. Secara umum, mereka mempunyai tujuan yang sama: untuk menyegerakkan akses kepada beberapa sumber. Satu-satunya perbezaan ialah muteks objek hanya boleh diperolehi oleh satu utas pada satu masa, manakala dalam kes semaphore, pembilang benang digunakan, dan beberapa daripada mereka boleh mengakses sumber sekaligus. Dan ini bukan sekadar persamaan kebetulan :) Sebenarnya, mutex ialah semafor satu tempat . Iaitu, ia adalah semaphore yang pembilangnya pada mulanya ditetapkan kepada 1. Ia juga dipanggil "semaphore binari" kerana pembilangnya hanya boleh mempunyai 2 nilai - 1 ("percuma") dan 0 ("sibuk"). Itu sahaja! Seperti yang anda lihat, semuanya ternyata tidak begitu mengelirukan :) Sekarang, jika anda ingin mengkaji topik multithreading dengan lebih terperinci di Internet, ia akan menjadi lebih mudah bagi anda untuk menavigasi konsep. Jumpa anda dalam pelajaran seterusnya! release()Semaphoreacquire()release()Apakah perbezaan antara mutex, monitor dan semaphore - 5
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION