Pour faire une analogie : un objet est comme une grande maison, la porte est toujours ouverte. Il existe de nombreuses pièces (ou méthodes) dans une maison. Ces salles sont soit verrouillées (méthode synchronisée), soit déverrouillées (méthode normale). Il y a une clé à la porte de la pièce. Cette clé peut ouvrir toutes les pièces verrouillées. De plus, je compare tous les threads qui souhaitent appeler les méthodes de cet objet aux personnes qui souhaitent entrer dans une certaine pièce de cette maison. C’est tout ce qu’il y a à dire, voyons comment ces choses fonctionnent les unes avec les autres.
Ici, nous clarifions d’abord nos prérequis. L'objet possède au moins une méthode synchronisée, sinon cette clé n'a aucune signification. Bien sûr, un tel thème n’existera pas chez nous.
Une personne veut entrer dans une pièce verrouillée. Elle se présente à la porte de la maison et y voit la clé (ce qui indique que personne d'autre ne veut encore utiliser la pièce verrouillée). Il est donc monté, a récupéré les clés et a utilisé les chambres comme il l'avait prévu. A noter qu'il rend la clé immédiatement après chaque utilisation de la pièce verrouillée. Même s'il souhaite utiliser deux pièces verrouillées d'affilée, il doit rendre la clé et la récupérer entre les deux.
Par conséquent, le principe d'utilisation des clés dans des circonstances normales est le suivant : "Empruntez-les au fur et à mesure que vous les utilisez et restituez-les dès que vous les utilisez".
À l'heure actuelle, d'autres personnes peuvent utiliser les pièces déverrouillées sans restriction. Une personne peut utiliser une pièce ou deux personnes peuvent utiliser une pièce. Il n'y a aucune restriction. Mais si quelqu’un veut entrer dans une pièce verrouillée, il doit courir vers la porte et regarder. Si vous avez la clé, vous pouvez bien sûr la prendre et partir. Si vous n'avez pas la clé, vous ne pouvez qu'attendre.
Si de nombreuses personnes attendent la clé, qui la recevra en premier lorsque la clé sera rendue ? Non garanti. Comme le gars de l'exemple précédent qui veut utiliser deux pièces verrouillées d'affilée, s'il y a d'autres personnes qui attendent la clé lorsqu'il rend la clé, il n'y a aucune garantie que ce gars puisse l'obtenir à nouveau. (La spécification JAVA indique clairement à de nombreux endroits qu'il n'y a aucune garantie, comme le temps qu'il faudra à Thread.sleep() pour revenir à l'exécution après un repos, quel thread avec la même priorité sera exécuté en premier et quand le le verrou pour accéder à l'objet est libéré, plusieurs threads dans le pool d'attente le recevront. Quel thread l'obtiendra en premier ? Etc. Je pense que la décision finale appartient à la JVM. La raison pour laquelle il n'y a aucune garantie est que lorsque la JVM prend la décision ci-dessus, elle ne porte pas un jugement simplement sur une seule condition, mais sur plusieurs conditions. de nombreuses conditions de jugement. Si vous les dites, cela peut affecter JAVA. La promotion est peut-être due à la protection de la propriété intellectuelle. SUN n'a donné aucune garantie et c'est compréhensible. Mais je pense que ces incertitudes ne sont pas totalement incertaines car l'ordinateur lui-même fonctionne selon les instructions. Il existe des règles à trouver. Quiconque a étudié les ordinateurs sait que le nom scientifique des nombres aléatoires dans les ordinateurs est des nombres pseudo-aléatoires, qui sont écrits par des personnes utilisant une certaine méthode. c'est certain. C'est beaucoup de problèmes et cela n'a pas beaucoup de sens, donc si vous n'êtes pas sûr, ne l'êtes pas.)
Regardons à nouveau les blocs de code synchronisés. C'est légèrement différent de la méthode de synchronisation.
1. En termes de taille, les blocs de code synchronisés sont plus petits que les méthodes synchronisées. Vous pouvez considérer un bloc de code synchronisé comme un espace dans une pièce déverrouillée séparé par un écran verrouillé.
2. Le bloc de code de synchronisation peut également spécifier manuellement la clé d'un autre objet. C'est comme spécifier quelle clé peut être utilisée pour ouvrir la serrure de cet écran. Vous pouvez utiliser la clé de cette maison, vous pouvez également spécifier la clé d'une autre maison pour l'ouvrir. Dans ce cas, vous devez courir vers l'autre maison. pour ouvrir la serrure. Obtenez cette clé et utilisez cette clé de maison pour ouvrir l'écran verrouillé de cette maison.
N'oubliez pas que la clé d'une autre maison que vous avez obtenue n'empêche pas les autres d'entrer dans les pièces non verrouillées de cette maison.
Pourquoi utiliser des blocs de code synchronisés ? Je pense que cela devrait être comme ceci : tout d'abord, la partie synchronisation du programme affecte l'efficacité de fonctionnement, et une méthode crée généralement d'abord des variables locales, puis effectue certaines opérations sur ces variables, telles que des calculs, l'affichage, etc. ; et la synchronisation couvre Plus il y a de code, plus l'impact sur l'efficacité est grave. Nous essayons donc généralement de limiter au maximum son impact. Comment faire ? Blocs de code synchronisés. Nous synchronisons uniquement les parties d'une méthode qui doivent être synchronisées, telles que les opérations.
De plus, le bloc de code de synchronisation peut spécifier la clé. Cette fonctionnalité présente l'avantage supplémentaire d'occuper la clé d'un objet pendant une certaine période de temps. Rappelez-vous ce que j'ai dit précédemment sur les principes d'utilisation des clés dans des circonstances normales. Ce ne sont pas des circonstances ordinaires. La clé que vous obtenez n'est pas renvoyée pour toujours, mais uniquement lorsque vous quittez le bloc de code synchronisé.
Utilisons l’analogie du gars plus tôt qui voulait utiliser deux pièces verrouillées d’affilée. Comment puis-je continuer à utiliser une autre pièce après avoir utilisé une pièce ? Utilisez des blocs de code synchronisés. Créez d’abord un autre fil de discussion, créez un bloc de code de synchronisation et pointez le verrou de ce bloc de code vers la clé de la maison. Alors démarrez ce fil. Tant que vous pouvez récupérer la clé de la maison lorsque vous entrez dans ce bloc de code, vous pouvez la conserver jusqu'à ce que vous quittiez ce bloc de code. En d'autres termes, vous pouvez même traverser toutes les pièces verrouillées de cette pièce, et même dormir (10*60*1000), mais il y a encore 1000 threads qui attendent la clé à la porte. C'est assez agréable.
Parlons de la corrélation entre la méthode sleep() et la clé. Si un thread est forcé de dormir () après avoir obtenu la clé et n'a pas terminé le contenu de synchronisation, la clé sera toujours là. La clé ne sera pas renvoyée tant qu'elle n'aura pas été réexécutée et que tout le contenu de synchronisation sera terminé. Rappelez-vous, le gars était juste fatigué du travail et est allé se reposer. Il n'a pas fini ce qu'il voulait faire. Afin d'empêcher les autres d'entrer dans la pièce et de semer le désordre à l'intérieur, il devait porter la seule clé sur son corps même lorsqu'il dormait.
Enfin, quelqu’un pourrait se demander pourquoi avons-nous besoin d’une clé pour ouvrir chaque porte, au lieu d’une clé pour chaque porte ? Je pense que c'est purement une question de complexité. Une clé pour une porte est certainement plus sûre, mais cela entraînera de nombreux problèmes. La génération, le stockage, l'acquisition, la restitution des clés, etc. Sa complexité peut augmenter géométriquement à mesure que le nombre de méthodes de synchronisation augmente, affectant sérieusement l'efficacité. Cela peut être considéré comme une question de compromis. Il n’est pas souhaitable de réduire considérablement l’efficacité pour augmenter un peu la sécurité.