Inhaltsverzeichnis
Sperren
synchronisierte Fehler
Methoden
ReentrantLock
Konstruktionsmethode
Gemeinsame Methoden
ReadWriteLock
ReentrantReadWriteLock
构造方法
常用的方法
参考文章
Heim Java javaLernprogramm Sperren Sie die Freigabe der Nutzungszusammenfassung

Sperren Sie die Freigabe der Nutzungszusammenfassung

Jun 23, 2017 am 10:50 AM
lock

Sperren

Im vorherigen Artikel haben wir darüber gesprochen, wie man das Schlüsselwort synchronisiert verwendet, um einen synchronen Zugriff zu erreichen. In diesem Artikel diskutieren wir dieses Problem weiter. Ab Java 5 wird eine weitere Möglichkeit zum Erreichen eines synchronen Zugriffs unter dem Paket java.util.concurrent.locks bereitgestellt, nämlich Lock.

Einige Freunde fragen sich vielleicht, warum wir eine Sperre bereitstellen müssen, da synchronisierter Zugriff durch Synchronisierung erreicht werden kann. Auf dieses Problem wird weiter unten eingegangen. Dieser Artikel beginnt mit den Mängeln der Synchronisierung, beschreibt dann die häufig verwendeten Klassen und Schnittstellen im Paket java.util.concurrent.locks und erörtert schließlich die folgenden Dinge zum Konzept von Sperren

synchronisierte Fehler

Wir haben zuvor gesagt, dass es zwei Situationen gibt, in denen ein synchronisierter Thread die Sperre aufhebt:

  1. Der Codeblock oder die synchronisierte Methode ist ausgeführt

  2. Wenn eine Ausnahme in einem Codeblock oder einer Synchronisationsmethode auftritt, gibt die JVM die Sperre automatisch frei

Sie können anhand der synchronisierten Freigabesperre oben erkennen, dass die Sperre erst freigegeben wird, wenn die Ausführung des synchronisierten Codeblocks abgeschlossen ist oder eine Ausnahme auftritt. Wenn das Programm im Codeblock aus E/A-Gründen blockiert ist, wird der Thread blockiert wird die Sperre nie aufheben, aber zu diesem Zeitpunkt führen andere Threads immer noch andere Programme aus. Dies wirkt sich stark auf die Ausführungseffizienz des Programms aus. Jetzt benötigen wir einen Mechanismus, der verhindern kann, dass der Thread auf unbestimmte Zeit wartet durch Sperre erfolgen

Darüber hinaus, wenn Es gibt ein Programm, das mehrere Lese-Threads und einen Schreib-Thread enthält Wir können wissen, dass synchronisiert nur von einem Thread ausgeführt werden kann, aber wir brauchen Mehrere Lesethreads können gleichzeitig gelesen werden, daher ist die Verwendung einer Synchronisierung definitiv nicht möglich, aber wir verwenden die Sperre auf die gleiche Weise. Dies ist möglich

Sperren

Wenn wir uns die API ansehen, können wir sehen, dass Lock eine Schnittstelle ist, sodass Objekte nicht direkt erstellt werden können. Wir können jedoch die von ihr implementierten Klassen zum Erstellen von Objekten verwenden. Machen Sie sich darüber keine Sorgen. Schauen wir uns zunächst an, welche Methoden implementiert sind durch die Lock-Klasse. Wir werden die spezifische Implementierung im Detail erläutern, wenn wir die von ihr implementierten Klassen

Methoden

  • lock() vorstellen , wenn nicht, wird es ewig warten

  • unlock() Sperre aufheben

  • tryLock() Versuchen Sie, die Sperre zu erhalten erfolgreich erworben, führen Sie sie aus. Wenn die Sperre nicht erfolgreich erworben wurde, gibt es keine Wartezeit.

  • lockInterruptibly() Wenn der aktuelle Thread nicht unterbrochen wird, wird die Sperre erworben.

ReentrantLock

ReentrantLock ist eine Klasse, die die Lock-Schnittstelle implementiert Dies bedeutet, dass es immer dem Thread zugewiesen wird, der kürzlich die Sperre erhalten hat. Um dieses Phänomen zu lösen, stellt die Konstruktionsmethode von ReentrantLock natürlich auch einen fairen Parameter bereit Fair ist wahr, es bedeutet, dass bei Verwendung des Fair-Zuteilungsmechanismus der Thread mit der längsten Wartezeit die Sperre erhält

Konstruktionsmethode

  • ReentrantLock() Erstellen Sie ein Objekt und verwenden Sie standardmäßig den Wiedereintrittsmechanismus

  • ReentrantLock(boolean fair) Wenn fair wahr ist, wird der faire Zuordnungsmechanismus verwendet

Gemeinsame Methoden

  • lock() Erwerben Sie die Sperre. Wenn sie nicht erworben wird, wird sie immer blockiert

Im Folgenden wird ein Programm verwendet, um die Verwendung der folgenden Sperrmethode zu demonstrieren. Der Code lautet wie folgt:

//实现接口的线程类public class MyThread implements Runnable {public ReentrantLock rLock = null;  //注意这里的锁一定要是全局变量,否则每一个线程都创建一把锁,那么将会毫无意义
 public MyThread() {this.rLock = new ReentrantLock(); // 创建默认的可重入锁}// 将unlock方法放在finally中确保执行中代码出现异常仍然能够释放锁,否则将会造成其它的线程阻塞public void display() {this.rLock.lock(); // 获取锁try {for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName() + "正在输出"+ i);
            }
        } finally {this.rLock.unlock(); // 释放锁,注意这步是一定需要的}

    }@Overridepublic void run() {this.display(); // 调用display方法}

}//线程的测试类,主要是创建对象启动线程public class Test {public static void main(String[] args) {final MyThread thread = new MyThread(); // 创建对象// 下面创建两个线程,并且直接启动,new Thread(thread).start();new Thread(thread).start();

    }
}
Nach dem Login kopieren

Führen Sie aus Geben Sie den obigen Code ein, um das unten gezeigte Ergebnis zu erhalten:

Sperren Sie die Freigabe der Nutzungszusammenfassung

Aus den obigen Ergebnissen können wir ersehen, dass die Threads eins ausgeben um einen, und der nächste kann erst ausgeführt werden, nachdem auf den Abschluss der Ausgabe eines Threads gewartet wurde. Ein Thread gilt hier nur für den Code zwischen Sperren und Entsperren, der andere Code wird nicht gesteuert

Hinweis: Die Erstellung hier kann wiederholt werden. Das gesperrte Objekt muss eine globale Variable für jeden Thread und ein Objekt sein, das gemeinsam genutzt werden kann. Wenn Sie dieses Objekt in der Anzeigemethode erstellen, ist es bedeutungslos Nicht jeder Thread verwendet die gleiche Sperre. Versuchen Sie zunächst, die Sperre zu erhalten, andernfalls führen Sie sie aus es wird nicht ewig warten

  • Verwenden Sie einen Code, um die folgende Methode auszuprobieren. Der Code lautet wie folgt:boolean tryLock()

执行后的Sperren Sie die Freigabe der Nutzungszusammenfassung如下图:

Sperren Sie die Freigabe der Nutzungszusammenfassung

从上面的Sperren Sie die Freigabe der Nutzungszusammenfassung我们知道线程0获取了锁开始执行,但是线程1并没有获取锁,但是使用的是tryLock并不是lock,因此不会一直等待下去,所以直接程序向下运行,直接跳过上锁的代码段,因此就输出了上面的那句话后直接结

ReadWriteLock

从API中可以知道,这个也是一个接口,用于实现读写线程,他有两个方法:Lock readLock(),Lock writeLock() 分别用于获得读锁和写锁,指定特定的锁可以实现特定的功能,比如读锁可以在写线程在执行的情况下可以实现多个读线程进行操作,下面我们来介绍它的具体的实现的类ReentrantReadWriteLock

ReentrantReadWriteLock

这个类也是一个可重入分配的类,当然前面已经说过了什么是可重入,现在我们来说说说这个类的详细的用法

构造方法

  • ReentrantReadWriteLock() 使用默认(非公平)的排序属性创建一个新的 ReentrantReadWriteLock。

  • ReentrantReadWriteLock(boolean fair) 使用给定的公平策略创建一个新的ReentrantReadWriteLock。

常用的方法

  • ReentrantReadWriteLock.ReadLock readLock() 用于返回读取操作的锁

前面已经说过读取操作的锁是用来实现多个线程共同执行的,代码如下:

//实现接口的线程类public class MyThread implements Runnable {public ReentrantReadWriteLock rwlock = null;public Lock rLock = null;public MyThread() {this.rwlock = new ReentrantReadWriteLock(); // 创建对象,使用的是非公平的this.rLock = this.rwlock.readLock(); // 获取读取锁对象}// 将unlock方法放在finally中确保执行中代码出现异常仍然能够释放锁,否则将会造成其它的线程阻塞public void display() {this.rLock.lock(); // 获取读取锁try {for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName() + "正在输出"+ i);
            }
        } finally {this.rLock.unlock(); // 释放锁,注意这步是一定需要的}

    }@Overridepublic void run() {this.display(); // 调用display方法}

}//线程的测试类,主要是创建对象启动线程public class Test {public static void main(String[] args) {final MyThread thread = new MyThread(); // 创建对象// 下面创建两个线程,并且直接启动,for(int i=0;i<5;i++)
        {new Thread(thread).start();
        }
        


    }
}
Nach dem Login kopieren

执行上面的程序Sperren Sie die Freigabe der Nutzungszusammenfassung如下:

Sperren Sie die Freigabe der Nutzungszusammenfassung

从上面的Sperren Sie die Freigabe der Nutzungszusammenfassung可以知道,其实使用读取操作是多个线程同时进行读取的操作,因此一定要小心谨慎的使用,根据自己的需求,一般不能在里面进行修改了,因为出现Sperren Sie die Freigabe der Nutzungszusammenfassung不准确的Sperren Sie die Freigabe der Nutzungszusammenfassung,这个就不多说了,相信大家都明白,总之要小心使用

  • ReentrantReadWriteLock.WriteLock writeLock() 返回用于写入操作的锁

写入操作的锁和读取操作的锁不一样了,因为一次只能允许一个线程执行写入操作。

并且如果一个线程已经占用了读锁,另外一个线程申请写锁将会一直等待线程释放读锁。

如果一个线程已经占用了写锁,另外一个线程申请读锁,那么这个线程将会一直等待线程释放写锁才能执行。

总之意思就是写线程和读线程不能同时执行,但是多个读线程可以同时执行

下面将使用一个程序详细的体会以下读写锁的综合使用,代码如下:

//实现接口的线程类public class MyThread {public ReentrantReadWriteLock rwlock = null;public Lock rLock = null;public Lock wLock = null;public ArrayList<Integer> arrayList = null;public MyThread() {this.rwlock = new ReentrantReadWriteLock(); // 创建对象,使用的是非公平的this.rLock = this.rwlock.readLock(); // 获取读取锁对象arrayList = new ArrayList<>(); // 实例化this.wLock = this.rwlock.writeLock(); // 获取写入锁对象}// 将unlock方法放在finally中确保执行中代码出现异常仍然能够释放锁,否则将会造成其它的线程阻塞// //向arraylist中写入数据public void put() {this.wLock.lock(); // 获取写入锁try {for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName()
                        + "正在执行写入操作,写入" + i);this.arrayList.add(i);
            }
        } finally {this.wLock.unlock();
        }

    }// 从arraylist中读取数据,这里只是随机读取使用的是get,并没有做什么修改,因为这仅仅是读取操作,如果进行了修改必须实现同步public void get() {this.rLock.lock(); // 获取读取操作的锁Random random = new Random();if (!arrayList.isEmpty()) {try {for (int i = 0; i < 10; i++) {int index = random.nextInt(this.arrayList.size() - 1);int data = this.arrayList.get(index);
                    System.out.println(Thread.currentThread().getName()
                            + "正在读取数据     " + data);
                }
            } finally {this.rLock.unlock();

            }
        } else {
            System.out.println("ArrayList为空");
        }

    }

}//线程的测试类,主要是创建对象启动线程public class Test {public static void main(String[] args) {final MyThread thread = new MyThread(); // 创建对象ArrayList<Thread> arrayList = new ArrayList<>();/*         * 创建8个读线程,2个写线程         */for (int i = 0; i < 2; i++) {
            arrayList.add(new Thread() {@Overridepublic void run() {
                    thread.put();
                }
            });

        }        for(int i=0;i<8;i++)
        {
            arrayList.add(new Thread(){@Overridepublic void run() {
                    thread.get();
                }
            });
        }        
        
        
        for (Thread t : arrayList) {
            t.start();
        }

    }
}
Nach dem Login kopieren

Sperren Sie die Freigabe der Nutzungszusammenfassung如下图:

Sperren Sie die Freigabe der Nutzungszusammenfassung

从上面可以看出写入线程都是一个一个执行的,读取线程是一起执行的

注意: 所有的锁对象对于线程来说必须是全局变量,否则毫无意义。读线程只能进行不影响线程安全性的操作,比如不能进行对数据的修改插入,如果想要进行修改的话必须还要使用锁对必要的代码实现同步操作

参考文章


Das obige ist der detaillierte Inhalt vonSperren Sie die Freigabe der Nutzungszusammenfassung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

So verwenden Sie Lock in Java-Multithreading So verwenden Sie Lock in Java-Multithreading May 12, 2023 pm 02:46 PM

Nach Jdk1.5 gibt es unter dem Paket java.util.concurrent.locks eine Reihe von Schnittstellen und Klassen für die Thread-Synchronisierung. Wenn es um die Thread-Synchronisierung geht, denkt jeder an das synchronisierte Schlüsselwort, bei dem es sich um ein integriertes Schlüsselwort handelt In Java wird die Thread-Synchronisierung durchgeführt, aber dieses Schlüsselwort weist viele Mängel auf und ist nicht sehr praktisch und intuitiv. Daher werden wir Lock im Folgenden vergleichen und erklären. Wenn wir das synchronisierte Schlüsselwort verwenden, treten normalerweise die folgenden Probleme auf: (1) Unkontrollierbarkeit, es ist nicht möglich, Sperren nach Belieben zu sperren und freizugeben. (2) Die Effizienz ist relativ gering. Beispielsweise lesen wir derzeit zwei Dateien gleichzeitig.

Welche Möglichkeiten gibt es, Lock in Java zu verwenden? Welche Möglichkeiten gibt es, Lock in Java zu verwenden? Apr 23, 2023 pm 08:52 PM

1. Funktion (1) Die Lock-Methode zum Erlangen von Sperren unterstützt Unterbrechungen, erwirbt sie nicht nach einer Zeitüberschreitung und ist nicht blockierend (2) Verbessert die Semantik, wo das Sperren und Entsperren ausgeschrieben werden muss (3) Lock-explizite Sperren können uns bringen Kommt mit guter Flexibilität, aber gleichzeitig müssen wir die Sperre manuell aufheben (4) Bedingungsbedingungsobjekt unterstützen (5) Erlauben Sie mehreren Lesethreads gleichzeitig den Zugriff auf gemeinsam genutzte Ressourcen 2. Sperrenverwendung // Holen Sie sich die Sperre voidlock() //Wenn der aktuelle Thread nicht unterbrochen wurde, erwirb die Sperre voidlockInterruptably()//Gib eine neue Bedingungsinstanz zurück, die an diese Sperrinstanz gebunden ist. ConditionnewCondition()//Sperre nur, wenn sie aufgerufen wird

Welche Funktionalität bietet die Java Lock-Klasse? Welche Funktionalität bietet die Java Lock-Klasse? Apr 21, 2023 am 08:16 AM

Hinweis 1. Lock ist eine Schnittstelle im Paket java.util.concurent, die eine Reihe von Sperroperationsmethoden definiert. 2. Die Lock-Schnittstelle umfasst hauptsächlich die Implementierungsklassen ReentrantLock, ReentrantReadWriteLock, ReentrantReadWriteLock und WriteLock. Im Gegensatz zu Synchronized bietet Lock verwandte Schnittstellen wie das Erfassen von Sperren und das Freigeben von Sperren, wodurch die Verwendung flexibler und die Bedienung komplexer wird. InstanceReentrantReadWriteLocklock=newReentrantReadWriteLock();Lockread

Warum müssen Sie Lock in Java bereitstellen, anstatt nur das synchronisierte Schlüsselwort zu verwenden? Warum müssen Sie Lock in Java bereitstellen, anstatt nur das synchronisierte Schlüsselwort zu verwenden? Apr 20, 2023 pm 05:01 PM

Zusammenfassung: Das synchronisierte Schlüsselwort wird in Java bereitgestellt, um sicherzustellen, dass nur ein Thread auf den synchronisierten Codeblock zugreifen kann. Warum wird die Lock-Schnittstelle auch im Java SDK-Paket bereitgestellt, da das synchronisierte Schlüsselwort bereitgestellt wurde? Ist das eine unnötige Neuerfindung des Rades? Heute werden wir dieses Thema gemeinsam besprechen. Das synchronisierte Schlüsselwort wird in Java bereitgestellt, um sicherzustellen, dass nur ein Thread auf den synchronisierten Codeblock zugreifen kann. Warum wird die Lock-Schnittstelle auch im Java SDK-Paket bereitgestellt, da das synchronisierte Schlüsselwort bereitgestellt wurde? Ist das eine unnötige Neuerfindung des Rades? Lassen Sie uns heute gemeinsam darüber diskutieren

Welche Methoden zur Sperrenerfassung gibt es in Java? Welche Methoden zur Sperrenerfassung gibt es in Java? May 19, 2023 pm 01:13 PM

1. Die Erfassungsmethoden lock(), tryLock(), tryLock(longtime, TimeUnitunit) und lockInterruptably() werden alle zum Erlangen von Sperren verwendet. (1) Die Methode lock() ist die am häufigsten verwendete Methode zum Erhalten von Sperren. Wenn die Sperre von einem anderen Thread erworben wurde, warten Sie. (2) Die tryLock()-Methode hat einen Rückgabewert, was bedeutet, dass sie verwendet wird, um zu versuchen, die Sperre zu erhalten. Wenn die Erfassung erfolgreich ist, gibt sie true zurück. Wenn die Erfassung fehlschlägt (d. h. die Sperre wurde von einer anderen erworben). Thread) gibt es false zurück, was bedeutet, dass die Methode sofort zurückkehrt, egal was passiert. Sie werden nicht dort warten, wenn Sie das Schloss nicht bekommen. (3) tryLoc

Häufige Probleme im Java-Technologie-Stack und ihre Lösungen Häufige Probleme im Java-Technologie-Stack und ihre Lösungen Sep 06, 2023 am 09:59 AM

Häufige Probleme im Java-Technologie-Stack und ihre Lösungen Bei der Entwicklung von Java-Anwendungen stoßen wir häufig auf einige Probleme, wie z. B. Leistungsprobleme, Speicherverluste, Thread-Sicherheit usw. In diesem Artikel werden einige häufige Probleme und ihre Lösungen vorgestellt und entsprechende Codebeispiele gegeben. 1. Leistungsprobleme 1.1 Leistungsprobleme durch häufige Erstellung von Objekten. Die häufige Erstellung von Objekten führt zu häufigem Auslösen der Speicherbereinigung und beeinträchtigt somit die Leistung des Programms. Die Lösung besteht darin, Objekt-Pooling oder Caching zu verwenden, um Objekte wiederzuverwenden. Beispielcode: //Objekte mithilfe des Objektpools wiederverwenden

PHP-Sicherheitsauthentifizierung mit Auth0 Lock PHP-Sicherheitsauthentifizierung mit Auth0 Lock Jul 24, 2023 am 11:16 AM

PHP-Sicherheitsüberprüfung durch Auth0Lock Mit der Entwicklung des Internets erfordern immer mehr Anwendungen eine Benutzerauthentifizierung und Sicherheitsüberprüfung, um die Privatsphäre und Datensicherheit der Benutzer zu schützen. PHP ist eine weit verbreitete Backend-Sprache, die viele Möglichkeiten zur Implementierung einer sicheren Validierung bietet. Auth0 ist eine beliebte Authentifizierungs- und Autorisierungsplattform, die Entwicklern eine flexible und sichere Möglichkeit zur Implementierung der Benutzerauthentifizierung bietet. Auth0Lock wird von Auth0 bereitgestellt

Was ist der Unterschied zwischen Lock und Synchronized in Java? Was ist der Unterschied zwischen Lock und Synchronized in Java? Apr 17, 2023 pm 07:19 PM

1. Aus funktionaler Sicht sind Lock und Synchronized beide Tools, die in Java zur Lösung von Thread-Sicherheitsproblemen verwendet werden. 2. Aus Funktionssicht ist Synchronized das Synchronisationsschlüsselwort in Java, Lock ist die im J.U.C.-Paket bereitgestellte Schnittstelle , und dies Die Schnittstelle verfügt über viele Implementierungsklassen, einschließlich der Implementierung wiedereintrittsfähiger Sperren wie ReentrantLock. Eine Möglichkeit besteht darin, das synchronisierte Schlüsselwort auf Methodenebene zu ändern Es kann im Codeblock verwendet werden. Der Lebenszyklus des synchronisierten Sperrobjekts wird verwendet, um den Umfang der Sperre zu steuern. Das Sperrobjekt ist ein statisches Objekt oder ein Klassenpaar.

See all articles