Zusammenfassung gängiger Sperren in Java
Unterscheiden Sie die einzelnen Sperrmechanismen und wie Sie sie verwenden.
Verwendungsmethode: Optimistisch Sperre und pessimistische Sperre | |
---|---|
Ein Thread und mehrere Prozesse erhalten dieselbe Sperre | |
Mehrere Threads teilen sich eine Sperre | |
Sollten mehrere Threads um die Warteschlange konkurrieren | |
1. Optimistische Sperre und pessimistische SperrePessimistische Sperre: Bei der Ausführung können nicht mehrere Personen gleichzeitig ausgeführt werden. In herkömmlichen relationalen Datenbanken werden viele solcher Sperrmechanismen verwendet, z. B. Zeilensperren, Tabellensperren, Lesesperren, Schreibsperren usw., die alle vor dem Betrieb gesperrt werden Wenn die Nummern konsistent sind oder nicht, werden die Daten mit einer Version hinzugefügt, die Daten werden synchron aktualisiert und die Versionsnummer wird hinzugefügt. Es wird nicht gesperrt, die Versionsnummer kann ermittelt werden und kann von mehreren Personen bedient werden, ähnlich wie beim Ticketraub im Leben. Jedes Mal, wenn Sie die Daten abrufen, denken Sie, dass andere sie nicht ändern werden, sodass sie nicht gesperrt werden. Beim Aktualisieren können Sie jedoch beurteilen, ob andere die Daten in diesem Zeitraum aktualisiert haben Zahlen. Optimistisches Sperren eignet sich für Anwendungstypen mit mehreren Lesevorgängen, wodurch der Durchsatz verbessert werden kann. Redis verwendet diesen Check-and-Set-Mechanismus, um Transaktionen zu implementieren. # Demonstrieren Sie pessimistische Sperren und optimistische Sperren durch bestimmte Fälle Im Redis-Framework Vor der Ausführung von Multi Führen Sie den Befehl watch aus Wenn Sie jedoch auf einem anderen Server exec eingeben, wird ein Fehler angezeigt.Da optimistisches Sperren verwendet wird, wird die Version angezeigt ändert sich nach der ÄnderungAllgemein:#🎜 🎜#Pessimistische Sperre: Wenn jede Person etwas alleine erledigt, sperren und entsperren. Lösen Sie das Problem der Parallelität. Es kann nur einzeln ausgeführt werden, was ineffizient ist. Optimistische Sperre: Bei jeder Ausführung wird die Datenversionsnummer verglichen. Wer zuerst einreicht, reicht die Version zuerst ein Sperre: nicht in Ordnung, Sie können in die Warteschlange springen Gerechte Sperre: relativ geringe Effizienz Unfaire Sperre: hohe Effizienz, aber Threads neigen zum Verhungern Durch diese Funktion Lock lock = new ReentrantLock(true);. Erstellen Sie eine Wiedereintrittssperre. True bedeutet faire Sperre, false bedeutet unfaire Sperre. Standardmäßige unfaire SperreDurch Anzeigen des QuellcodesReentrantLock(true) mit Parametern ist eine faire SperreReentrantLock(false) ist eine unfaire Sperre Rufen Sie hauptsächlich NonfairSync() und FairSync() aufwatch key1 [key2] Nach dem Login kopieren
public ReentrantLock() { sync = new NonfairSync(); } /** * Creates an instance of {@code ReentrantLock} with the * given fairness policy. * * @param fair {@code true} if this lock should use a fair ordering policy */ public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); } Nach dem Login kopieren sind alle A-Threads Ausführung, aber der BC-Thread wurde nicht ausgeführt und es erscheint eine unfaire Sperre Um seine Einstellungen gezielt zu ändern, können Sie den Code über eine parametrisierte Konstruktionsmethode in der wiedereintrittsfähigen Sperre #🎜 ändern 🎜# Für privates Finale ReentrantLock lock = new ReentrantLock(true);Der Code-Screenshot ist3. Wiedereintrittssperre# 🎜🎜# Wiedereintrittssperren werden auch rekursive Sperren genanntUnd mit den Wiedereintrittssperren können Sie in die innere Struktur gelangen, nachdem Sie die erste geknackt habenstatic final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; /** * Acquires only if reentrant or queue is empty. */ final boolean initialTryLock() { Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (!hasQueuedThreads() && compareAndSetState(0, 1)) { setExclusiveOwnerThread(current); return true; } } else if (getExclusiveOwnerThread() == current) { if (++c < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(c); return true; } return false; } Nach dem Login kopieren Die oben genannten sind synchronisierte Sperrmechanismen Im Folgenden wird der Sperrmechanismus erläutert //第一步 创建资源类,定义属性和和操作方法 class LTicket { //票数量 private int number = 30; //创建可重入锁 private final ReentrantLock lock = new ReentrantLock(true); //卖票方法 public void sale() { //上锁 lock.lock(); try { //判断是否有票 if(number > 0) { System.out.println(Thread.currentThread().getName()+" :卖出"+(number--)+" 剩余:"+number); } } finally { //解锁 lock.unlock(); } } } public class LSaleTicket { //第二步 创建多个线程,调用资源类的操作方法 //创建三个线程 public static void main(String[] args) { LTicket ticket = new LTicket(); new Thread(()-> { for (int i = 0; i < 40; i++) { ticket.sale(); } },"AA").start(); new Thread(()-> { for (int i = 0; i < 40; i++) { ticket.sale(); } },"BB").start(); new Thread(()-> { for (int i = 0; i < 40; i++) { ticket.sale(); } },"CC").start(); } } Nach dem Login kopieren 4 geschrieben werden. Lese-/Schreibsperre (gemeinsame Sperre und exklusive Sperre) #🎜 🎜# Die Lesesperre ist eine gemeinsame Sperre und die Schreibsperre ist eine exklusive Sperre. Lese-/Schreibsperren verwalten eine Reihe von Sperren, eine davon ist eine schreibgeschützte Sperre und die andere ist eine Schreibsperre.Lese-/Schreibsperre: Auf eine Ressource können mehrere Lese-Threads oder ein Schreib-Thread zugreifen, Lese- und Schreib-Threads können jedoch nicht gleichzeitig vorhanden sein. Gegenseitiger Schreibausschluss, gemeinsame Lese-/Lesesperre (exklusive Schreibsperre, gemeinsame Lesesperre, Priorität der Schreibsperre ist höher als die Lesesperre)Lese-/Schreibsperre ReentrantReadWriteLock Die Lesesperre ist ReentrantReadWriteLock.ReadLock, readLock()-Methode Die Schreibsperre ist ReentrantReadWriteLock.WriteLock, writeLock()-Methode Erstellen Sie ein Lese-/Schreibsperrobjekt, privat ReadWriteLock rwLock = neues ReentrantReadWriteLock (); #🎜 🎜#Schreibsperre rwLock.writeLock().lock();, entsperren rwLock.writeLock().unlock();Lesesperre rwLock.readLock() .lock() ;, Entsperren ist rwLock.readLock().unlock();Fallanalyse: Multithreading simulieren, um Daten in der Karte abzurufen und zu lesen# 🎜🎜##🎜 🎜#Der vollständige Code lautet wie folgtObject o = new Object(); new Thread(()->{ synchronized(o) { System.out.println(Thread.currentThread().getName()+" 外层"); synchronized (o) { System.out.println(Thread.currentThread().getName()+" 中层"); synchronized (o) { System.out.println(Thread.currentThread().getName()+" 内层"); } } } },"t1").start(); Nach dem Login kopieren Mutex-Sperre ist eine herkömmliche Implementierung einer exklusiven Sperre, was bedeutet, dass eine bestimmte Ressource Ermöglicht nur einem Besucher gleichzeitig den Zugriff mit Einzigartigkeit und Exklusivität.它是为实现保护共享资源而提出一种锁机制。其实,自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名 通俗的来说就是一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。获取锁的线程一直处于活跃状态,但是并没有执行任何有效的任务。 其特点:
其模拟算法如下 do{ b=1; while(b){ lock(bus); b = test_and_set(&lock); unlock(bus); } //临界区 //lock = 0; //其余部分 }while(1) Nach dem Login kopieren 7. 无锁 / 偏向锁 / 轻量级锁 / 重量级锁
|
Das obige ist der detaillierte Inhalt vonWas sind die Mechanismen verschiedener Sperren in Java?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!