Mutex in Java
In der Welt der Informatik ist Mutual Exclusion oder Mutex als Eigenschaft der Parallelitätskontrolle bekannt. Jeder Computer arbeitet die kleinste Sequenz von programmierten Befehlen, die als Thread bekannt sind. Der Computer arbeitet gleichzeitig an einem einzelnen Thread. Lassen Sie uns zum besseren Verständnis in einige weitere Aspekte eintauchen.
Threading und Multithreading
CPU arbeitet an Threads für Multitasking. Jeder Prozess funktioniert, indem er ständig mit sehr hoher Geschwindigkeit von Thread zu Thread wechselt. Wenn wir uns beispielsweise ein Video ansehen, befindet sich der Ton des Videos in einem anderen Thread und das Bild in einem anderen. Der ständige Wechsel zwischen diesen beiden ist sehr schnell und wird als Multithreading bezeichnet.
Threads in Java
Das Erstellen eines Threads in Java erfolgt durch das Erweitern einer Klasse und das Implementieren einer Schnittstelle. Multithreading ist eine Java-Funktion, die die gleichzeitige Ausführung von zwei oder mehr Teilen eines Programms ermöglicht, um die CPU-Effizienz zu maximieren. Ein Thread ist ein Bestandteil eines solchen Programms. Threads sind daher leichtgewichtige Prozesse innerhalb von Prozessen.
Mutex
In einem Multithread-Programm müssen möglicherweise zwei oder mehr Threads gleichzeitig auf eine gemeinsam genutzte Ressource zugreifen, was zu unerwartetem Verhalten führt. Datenstrukturen, Eingabe-Ausgabe-Geräte, Dateien und Netzwerkverbindungen sind Beispiele für gemeinsam genutzte Ressourcen.
Dies wird als Race-Condition bezeichnet. Der Schlüsselabschnitt des Programms ist der Teil des Programms, der auf die gemeinsam genutzte Ressource zugreift. Als Ergebnis müssen wir den Zugriff auf den kritischen Teil synchronisieren, um eine Race-Condition zu vermeiden.
Die einfachste Art von Synchronizer ist ein Mutex (oder gegenseitiger Ausschluss), der sicherstellt, dass nur ein Thread den wesentlichen Bereich eines Computerprogramms gleichzeitig ausführen kann. Es wird von einer Klasse namens semaphore
implementiert.
Ein Thread ruft den Mutex ab, greift dann auf den entscheidenden Abschnitt zu und gibt schließlich den Mutex frei, um auf einen kritischen Bereich zuzugreifen. Währenddessen werden alle anderen Threads blockiert, bis der Mutex freigegeben wird. Ein Thread kann in den kritischen Abschnitt eintreten, sobald er den kritischen Bereich verlässt.
Für Mutex gibt es zwei Methoden zum Sperren und Entsperren. Sie werden als acquire()
bzw. release()
bezeichnet. Sehen Sie sich nun das Beispiel unten an.
Erfahren Sie mehr über Mutex hier.
import java.util.LinkedList; // linked list import
import java.util.concurrent.Semaphore; // semaphore import
public class Mutex {
static LinkedList<String> WorkingQueue = new LinkedList<String>();
// track the record of works
static Semaphore mutex1 = new Semaphore(0); // creating a Semaphore To ImplementLogic
static Semaphore mutex = new Semaphore(1); // Creating A Mutex
}
Im obigen Beispiel haben wir zwei Mutex-Objekte mit den Namen mutex
und mutex1
erstellt. Wir verwenden mutex1
, um den Wechsel zwischen zwei Threads zu steuern. Der Grund für das Erstellen der verknüpften Liste besteht darin, eine Erfolgsbilanz von Threads zu haben. Jetzt fügen wir zwei Threads in den obigen Code ein. Zwei Threads mit den Namen Producer
und Consumer
.
import java.util.LinkedList; // linked list import
import java.util.concurrent.Semaphore; // semaphore import
public class Mutex {
static LinkedList<String> WorkingQueue = new LinkedList<String>();
// track the record of works
static Semaphore mutex1 = new Semaphore(0); // creating a Semaphore To ImplementLogic
static Semaphore mutex = new Semaphore(1); // Creating A Mutex
static class Producer extends Thread {
public void run() { // default run method of thread
int counter = 1;
try {
while (true) {
String threadName = Thread.currentThread().getName()
+ counter++; // counter is added to have the thread number being used
mutex.acquire(); // Acquiring Lock before Producing so the consumer cannot consume.
WorkingQueue.add(threadName);
System.out.println("Producer is prdoucing producing: " + threadName);
mutex.release(); // releasing After Production ;
mutex1.release(); // relesing lock for consumer...so consumer can consume after production
Thread.sleep(2000); // just to Reduce the Execution Speed
}
} catch (Exception e) { /*nothing */
}
}
}
static class Consumer extends Thread {
String consumerName;
public Consumer(String name) {
this.consumerName = name;
}
public void run() {
try {
while (true) {
mutex1.acquire(); /// Again Acquiring So no production while consuming
mutex.acquire(); // Acquring Other consumers lock one consume at one time
String result = "";
for (String value : WorkingQueue) {
result = value + ",";
}
System.out.println(consumerName + " consumes value: " + result
+ "Total Size working Queue Size " + WorkingQueue.size() + "\n");
mutex.release(); // releasing lock for other consumers.
}
} catch (Exception e) {
}
}
public static void main(String[] args) {
Producer producer = new Producer();
producer.start();
Consumer c1 = new Consumer("Bill Gates");
Consumer c2 = new Consumer("Jeff Bezoz");
Consumer c3 = new Consumer("Mark Zukerberg");
c1.start();
c2.start();
c3.start();
}
}
}
Erläuterung
Der obige Code ist ebenfalls selbsterklärend, aber diese Erklärung wird die Verwirrung beseitigen.
Im Producer
-Thread
Wenn Sie das obige Programm ausführen, erstellt es einen producer
-Thread. Innerhalb dieses Threads gibt es eine while
-Schleife, die auf unbestimmte Zeit ausgeführt wird. Der String threadName
dient nur zur Anzeige der Thread-Ausführung. Das Objekt mutex
erhält die Sperre, damit der Consumer-Thread funktionsfähig ist. (Der Hauptzweck von Mutex, die Kontrolle über die Parallelität zu erlangen).
Danach wird der Thread Produzent
funktionsfähig. Dann müssen wir diesen Thread für die Produktion freigeben. Im Thread producer
werden wir mutex1
freigeben, das Objekt, das für den Wechsel zwischen consumer
und producer
zuständig ist. Nach der Freigabe beginnen die Verbraucher zu konsumieren, dh der Thread consumer
wird funktionsfähig sein.
Im Consumer
-Thread
Gleich nachdem wir in den consumer
-Thread eingestiegen sind, haben wir mutex1
erworben, um die Produktion während des Konsums zu stoppen. Wie Sie sehen, haben wir drei Konsumenten unter den Namen C1
, C2
und C3
angelegt. Damit ein Konsument gleichzeitig funktionstüchtig sein kann, haben wir auch mutex
erworben.
Danach wird C1
funktionsfähig, während C2
und C3
erfasst werden. Nach Abschluss wird mutex
wieder freigegeben, damit der andere Konsument funktionsfähig ist.
So funktioniert Mutex in Java. Nachdem Sie das obige Programm ausgeführt haben. Es zeigt ständig die aktuelle Anzahl der verwendeten producer
-Threads und den Namen des consumers
an, der diese verwendet.
Die Größe wird während der Ausführung des Programms weiter erhöht.
Haider specializes in technical writing. He has a solid background in computer science that allows him to create engaging, original, and compelling technical tutorials. In his free time, he enjoys adding new skills to his repertoire and watching Netflix.
LinkedIn