CodeGym /Java Blog /Acak /Perbedaan Antara Mutex, Monitor, dan Semaphore
John Squirrels
Level 41
San Francisco

Perbedaan Antara Mutex, Monitor, dan Semaphore

Dipublikasikan di grup Acak
Hai! Saat Anda mempelajari multithreading di CodeGym, Anda sering menemukan konsep "mutex" dan "monitor". Tanpa mengintip, dapatkah Anda mengatakan perbedaannya? :) Jika ya, selamat! Jika tidak (ini yang paling umum), tidak mengherankan. "Mutex" dan "monitor" sebenarnya adalah konsep yang terkait. Selain itu, saat Anda membaca pelajaran dan menonton video tentang multithreading di situs web lain, Anda akan menemukan konsep serupa lainnya: "semaphore". Ini juga memiliki fungsi yang sangat mirip dengan monitor dan mutex. Itu sebabnya kami akan menyelidiki ketiga istilah ini. Kami akan melihat beberapa contoh dan sampai pada pemahaman yang pasti tentang bagaimana konsep-konsep ini berbeda satu sama lain :)

Mutex

Mutex (atau kunci) adalah mekanisme khusus untuk menyinkronkan utas. Satu "dilampirkan" ke setiap objek di Java — Anda sudah tahu itu :) Tidak masalah jika Anda menggunakan kelas standar atau membuat kelas Anda sendiri, misalnya Kucing dan Anjing : semua objek dari semua kelas memiliki mutex . Istilah "mutex" berasal dari "MUTual EXclusion", yang dengan sempurna menggambarkan tujuannya. Seperti yang kami katakan di salah satu pelajaran kami sebelumnya, mutex memungkinkan untuk memastikan bahwa hanya satu utas pada satu waktu yang memiliki akses ke objek. Contoh kehidupan nyata yang populer dari mutex melibatkan toilet. Ketika seseorang memasuki sekat toilet, dia mengunci pintu dari dalam. Toilet itu seperti benda yang bisa diakses oleh banyak utas. Kunci di pintu partisi seperti mutex, dan barisan orang di luar melambangkan utas. Kunci pintu adalah mutex toilet: memastikan hanya satu orang yang bisa masuk. Apa perbedaan antara mutex, monitor, dan semaphore?  - 2Dengan kata lain, hanya satu utas pada satu waktu yang dapat bekerja dengan sumber daya bersama. Upaya oleh utas lain (orang) untuk mendapatkan akses ke sumber daya yang ditempati akan gagal. Mutex memiliki beberapa fitur penting. Pertama , hanya dua status yang memungkinkan: "tidak terkunci" dan "terkunci". Ini membantu kami memahami cara kerjanya: Anda dapat menggambar kesejajaran dengan variabel Boolean (benar/salah) atau bilangan biner (0/1). , negara tidak dapat dikontrol secara langsung. Java tidak memiliki mekanisme yang memungkinkan Anda mengambil objek secara eksplisit, mendapatkan mutexnya, dan menetapkan status yang diinginkan. Dengan kata lain, Anda tidak dapat melakukan sesuatu seperti:

Object myObject = new Object();
Mutex mutex = myObject.getMutex();
mutex.free();
Ini berarti Anda tidak dapat melepaskan mutex objek. Hanya mesin Java yang memiliki akses langsung ke sana. Pemrogram bekerja dengan mutex melalui alat bahasa.

Memantau

Monitor adalah "superstruktur" tambahan di atas mutex. Faktanya, monitor adalah potongan kode yang "tidak terlihat" oleh pemrogram. Ketika kami berbicara tentang mutex sebelumnya, kami memberikan contoh sederhana:

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
       }
   }
}
Di blok kode yang ditandai dengan kata kunci yang disinkronkan , mutex objek obj kita diperoleh. Bagus, kita bisa mendapatkan kuncinya, tapi bagaimana sebenarnya "perlindungan" itu diberikan? Saat kita melihat kata disinkronkan , apa yang mencegah utas lain memasuki blok? Perlindungan berasal dari monitor! Kompiler mengubah kata kunci yang disinkronkan menjadi beberapa bagian kode khusus. Sekali lagi, mari kita kembali ke contoh kita dengan metode doSomething() . Kami akan menambahkannya:

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 terjadi "di bawah tenda" setelah kompiler mengonversi kode 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;
   }
}
Tentu saja, ini bukan contoh nyata. Di sini, kami menggunakan kode mirip Java untuk menggambarkan apa yang terjadi di dalam mesin Java. Yang mengatakan, pseudo-code ini memberikan pemahaman yang sangat baik tentang apa yang sebenarnya terjadi dengan objek dan utas di dalam blok yang disinkronkan dan bagaimana kompiler mengubah kata kunci ini menjadi beberapa pernyataan yang "tidak terlihat" oleh pemrogram. Pada dasarnya, Java menggunakan kata kunci yang disinkronkan untuk mewakili monitor . Semua kode yang muncul sebagai pengganti kata kunci yang disinkronkan pada contoh terakhir adalah monitor.

Tiang sinyal

Kata lain yang akan Anda temui dalam studi pribadi Anda tentang multithreading adalah "semaphore". Mari kita cari tahu apa ini dan apa bedanya dengan monitor dan mutex. Semafor adalah alat untuk menyinkronkan akses ke beberapa sumber daya. Ciri khasnya adalah menggunakan penghitung untuk membuat mekanisme sinkronisasi. Penghitung memberi tahu kami berapa banyak utas yang dapat mengakses sumber daya bersama secara bersamaan. Apa perbedaan antara mutex, monitor, dan semaphore?  - 3Semaphore di Java diwakili oleh kelas Semaphore . Saat membuat objek semafor, kita dapat menggunakan konstruktor berikut:

Semaphore(int permits)
Semaphore(int permits, boolean fair)
Kami meneruskan yang berikut ke konstruktor:
    int permits — nilai awal dan maksimum penghitung. Dengan kata lain, parameter ini menentukan berapa banyak utas yang dapat mengakses sumber daya bersama secara bersamaan;
  • boolean fair — menetapkan urutan di mana utas akan mendapatkan akses. Jika adil benar, maka akses diberikan ke utas yang menunggu sesuai urutan yang mereka minta. Jika salah, maka urutan ditentukan oleh penjadwal utas.
Contoh klasik penggunaan semaphore adalah masalah makan filsuf. Apa perbedaan antara mutex, monitor, dan semaphore?  - 4Untuk memudahkan pemahaman, kami akan sedikit menyederhanakannya. Bayangkan kita memiliki 5 filsuf yang perlu makan siang. Selain itu, kami memiliki satu meja yang dapat menampung tidak lebih dari dua orang secara bersamaan. Tugas kita adalah memberi makan semua filsuf. Tak satu pun dari mereka yang kelaparan, dan tak satu pun dari mereka yang harus "menghalangi" satu sama lain saat mencoba duduk di meja (kita harus menghindari kebuntuan). Seperti inilah tampilan kelas filsuf kita:

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 kode 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 membuat semafor yang penghitungnya disetel ke 2 untuk memenuhi syarat: hanya dua filsuf yang dapat makan pada waktu yang sama. Artinya, hanya dua utas yang dapat berjalan pada saat yang sama, karena kelas Filsuf kami mewarisi Thread ! Metode acquire () dan release() dari kelas Semaphore mengontrol penghitung aksesnya. Metode acquire() meminta semafor untuk akses ke sumber daya. Jika penghitung >0, maka akses diberikan dan penghitung dikurangi 1. Rilis ()metode "melepaskan" akses yang diberikan sebelumnya, mengembalikannya ke penghitung (meningkatkan penghitung akses semafor sebanyak 1). Apa yang kita dapatkan ketika kita menjalankan program? Apakah masalah terpecahkan? Apakah para filsuf kita tidak akan berperang sambil menunggu giliran? :) Inilah keluaran konsol yang kami dapatkan:

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 berhasil! Dan meskipun Thales harus makan sendirian, saya rasa kami tidak menyinggung perasaannya :) Anda mungkin telah memperhatikan beberapa kesamaan antara mutex dan semaphore. Memang, mereka memiliki misi yang sama: menyinkronkan akses ke beberapa sumber daya. Apa perbedaan antara mutex, monitor, dan semaphore?  - 5Satu-satunya perbedaan adalah bahwa mutex objek dapat diperoleh hanya dengan satu utas pada satu waktu, sedangkan dalam kasus semaphore, yang menggunakan penghitung utas, beberapa utas dapat mengakses sumber daya secara bersamaan. Ini bukan hanya kebetulan :) Mutex sebenarnya adalah semafordengan hitungan 1. Dengan kata lain, itu adalah semafor yang dapat menampung satu utas. Ini juga dikenal sebagai "semafor biner" karena penghitungnya hanya dapat memiliki 2 nilai — 1 ("tidak terkunci") dan 0 ("terkunci"). Itu dia! Seperti yang Anda lihat, ini tidak terlalu membingungkan :) Sekarang, jika Anda ingin mempelajari multithreading lebih detail di Internet, akan lebih mudah bagi Anda untuk menavigasi konsep-konsep ini. Sampai jumpa di pelajaran selanjutnya!
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION