Le code qui est sûr lorsqu'il est appelé par plusieurs threads en même temps est appelé sécurité des threads. Si un morceau de code est thread-safe, il ne contient pas de conditions de concurrence. Les conditions de concurrence se produisent uniquement lorsque plusieurs threads mettent à jour les ressources partagées. Il est donc important de savoir quand les threads Java exécutent des ressources partagées.
Variables locales
Les variables locales sont stockées dans la propre pile de chaque thread. Cela signifie que les variables locales ne sont pas partagées entre les threads. Cela signifie également que toutes les variables primitives locales sont thread-safe. Voici un exemple :
public void someMethod(){ long threadSafeInt = 0; threadSafeInt++; }
Référence d'objet local
Les références locales aux objets sont un peu différentes. La référence elle-même ne sera pas partagée. Cependant, une référence à cet objet ne peut pas être stockée sur la pile de chaque thread. Tous les objets sont stockés dans le tas partagé.
Un objet créé localement est thread-safe s'il n'échappe pas à la méthode dans laquelle il a été créé. En fait, vous pouvez également le transmettre à d'autres méthodes, et ce tant que les méthodes de l'objet transmis ne sont pas disponibles pour les autres threads.
Voici un exemple :
public void someMethod(){ LocalObject localObject = new LocalObject(); localObject.callMethod(); method2(localObject); } public void method2(LocalObject localObject){ localObject.setValue("value"); }
L'instance LocalObject dans cet exemple ne peut pas être récupérée à partir de cette méthode Renvoyé et ne peut pas être transmis à d’autres objets. Ceci est accessible depuis l’extérieur de la méthode someMethod. Chaque thread exécutant la méthode someMethod créera sa propre instance LocalObject et l'attribuera à la référence localObject. Par conséquent, cette utilisation est thread-safe.
En fait, toute cette méthode someMethod est thread-safe. Même si cette instance de localObject est transmise en tant que paramètre à d’autres méthodes de la même classe ou à d’autres classes, son utilisation est thread-safe.
Bien sûr, la seule exception est si l'une de ces méthodes est appelée avec un LocalObject comme argument, stockant l'instance LocalObject d'une manière ou d'une autre, permettant l'accès à partir d'autres threads.
Variables membres de l'objet
Les variables membres de l'objet (champs) sont stockées sur le tas avec l'objet. Par conséquent, si deux threads appellent une méthode sur la même instance d’objet et que cette méthode met à jour les variables membres de l’objet, la méthode entière n’est pas thread-safe. Voici un exemple :
public class NotThreadSafe{ StringBuilder builder = new StringBuilder(); public add(String text){ this.builder.append(text); } }
Si deux threads appellent la méthode add simultanément sur la même instance NotThreadSafe, cela provoquera une condition de concurrence critique. Par exemple :
NotThreadSafe sharedInstance = new NotThreadSafe(); new Thread(new MyRunnable(sharedInstance)).start(); new Thread(new MyRunnable(sharedInstance)).start(); public class MyRunnable implements Runnable{ NotThreadSafe instance = null; public MyRunnable(NotThreadSafe instance){ this.instance = instance; } public void run(){ this.instance.add("some text"); } }
Remarquez comment les deux instances MyRunnable partagent la même instance NotThreadSafe. Par conséquent, une condition de concurrence critique se produit lorsqu’ils appellent la méthode add.
Cependant, si deux threads appellent la méthode add simultanément sur des instances différentes, cela ne provoquera pas de condition de concurrence critique. Voici un exemple du précédent, légèrement modifié :
new Thread(new MyRunnable(new NotThreadSafe())).start(); new Thread(new MyRunnable(new NotThreadSafe())).start();
Maintenant, chaque thread a sa propre instance NotThreadSafe, ils appellent donc cela add. Les méthodes n'interfèrent pas les unes avec les autres . Ce code n'a aucune condition de concurrence. Ainsi, même si un objet n’est pas thread-safe, il peut toujours être utilisé de cette manière sans provoquer de situation de concurrence critique.
Règles de débordement du contrôle des threads
Lorsque vous essayez de décider si l'accès de votre code à une ressource est thread-safe, vous pouvez utiliser les règles suivantes :
If a resource is created, used and disposed within the control of the same thread, and never escapes the control of this thread, the use of that resource is thread safe.
Une ressource peut être n'importe quelle ressource partagée, comme un objet, un tableau, un fichier, une connexion à une base de données, un socket, etc. En Java, vous ne pouvez pas toujours détruire explicitement un objet, donc « détruit » signifie que l'objet est manquant ou a une référence nulle.
Même si l'utilisation d'un objet est thread-safe, si cet objet pointe vers une ressource partagée comme un fichier ou une base de données, votre application dans son ensemble peut ne pas être Thread. en sécurité maintenant. Par exemple, si le thread 1 et le thread 2 créent chacun leurs propres connexions à la base de données, la connexion 1 et la connexion 2, chacune utilisant sa propre connexion, sont thread-safe. Mais l'utilisation de la base de données pointée par cette connexion peut ne pas être thread-safe. Par exemple, si deux threads exécutent ce code en même temps et qu'ils vérifient cet enregistrement, il y a ici un risque qu'ils finissent tous par être insérés sur le même enregistrement. Comme indiqué ci-dessous :
check if record X exists if not, insert record X
Ce qui précède est le contenu des fils de discussion Java et des ressources partagées. Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois (www.php.cn) !
Thread 1 checks if record X exists. Result = no Thread 2 checks if record X exists. Result = no Thread 1 inserts record X Thread 2 inserts record X