--- aliases: tags: - maturity/🌱 date: 2024-10-09 zero-link: parents: linked: --- synchronized β€” это ΠΎΠ΄ΠΈΠ½ ΠΈΠ· ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹Ρ… ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠΎΠ² Π² Java для управлСния [[ΠœΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒ Π² Java|ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒΡŽ]] ΠΈ обСспСчСния бСзопасности ΠΏΡ€ΠΈ доступС ΠΊ раздСляСмым рСсурсам. Π­Ρ‚ΠΎΡ‚ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΠΈΡ‚ΡŒ доступ ΠΊ критичСским сСкциям ΠΊΠΎΠ΄Π°, Ρ‚Π΅ΠΌ самым прСдотвращая состояния Π³ΠΎΠ½ΠΊΠΈ ([[../other/Race condition|race conditions]]). **Как Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ synchronized** Synchronized ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒΡΡ ΠΊ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°ΠΌ ΠΈΠ»ΠΈ Π±Π»ΠΎΠΊΠ°ΠΌ ΠΊΠΎΠ΄Π°. Когда ΠΏΠΎΡ‚ΠΎΠΊ Π²Ρ…ΠΎΠ΄ΠΈΡ‚ Π² ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΈΠ»ΠΈ Π±Π»ΠΎΠΊ, ΠΏΠΎΠΌΠ΅Ρ‡Π΅Π½Π½Ρ‹ΠΉ `synchronized`, ΠΎΠ½ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ [[ΠœΠΎΠ½ΠΈΡ‚ΠΎΡ€ Π² Java|ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€]] (lock) Π½Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, связанный с этим ΠΊΠΎΠ΄ΠΎΠΌ. Π”Ρ€ΡƒΠ³ΠΈΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠΈ Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ доступ ΠΊ этому ΠΊΠΎΠ΄Ρƒ Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ освобоТдСн. Π­Ρ‚ΠΎ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚, Ρ‡Ρ‚ΠΎ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½ ΠΏΠΎΡ‚ΠΎΠΊ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ Π΄Π°Π½Π½Ρ‹ΠΉ ΠΊΠΎΠ΄. Π’ этом ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅, `synchronized` Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ `increment` ΠΈ `getCount` Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ нСсколькими ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ, прСдотвращая Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Ρ‹Π΅ обновлСния ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ `count`. ```java public class Counter { private int count = 0; public synchronized void increment() { count++; } public synchronized int getCount() { return count; } } ``` Иногда ΡƒΠ΄ΠΎΠ±Π½Π΅Π΅ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π½Π΅ вСсь ΠΌΠ΅Ρ‚ΠΎΠ΄, Π° Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π΅Π³ΠΎ Ρ‡Π°ΡΡ‚ΡŒ. Π’ этом случаС ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π±Π»ΠΎΠΊ `synchronized`: ```java public void increment() { synchronized (this) { count++; } } ``` **ΠžΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΠΈ** - **ΠœΠΎΠ½ΠΈΡ‚ΠΎΡ€Ρ‹ привязаны ΠΊ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌ**, Π° Π½Π΅ ΠΊ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°ΠΌ. Если Π²Ρ‹ синхронизируСтС ΠΌΠ΅Ρ‚ΠΎΠ΄ экзСмпляра (instance method), Ρ‚ΠΎ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΎΠΌ являСтся Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ (this). Если ΠΌΠ΅Ρ‚ΠΎΠ΄ статичСский, Ρ‚ΠΎ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΎΠΌ выступаСт сам класс (ClassName.class). - **Π‘Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ ΠΌΠΎΠ³ΡƒΡ‚ привСсти ΠΊ Π²Π·Π°ΠΈΠΌΠ½ΠΎΠΉ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ΅** ([[../../../../_inbox/Deadlock|deadlock]]), Ссли Π΄Π²Π° ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΏΡ‹Ρ‚Π°ΡŽΡ‚ΡΡ Π·Π°Ρ…Π²Π°Ρ‚ΠΈΡ‚ΡŒ Π΄Ρ€ΡƒΠ³ Ρƒ Π΄Ρ€ΡƒΠ³Π° ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€Ρ‹ Π² Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠΌ порядкС. **ΠžΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΡ** - **Бинхронизация сниТаСт ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ**, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΏΠΎΡ‚ΠΎΠΊΠΈ Π²Ρ‹Π½ΡƒΠΆΠ΄Π΅Π½Ρ‹ ΠΎΠΆΠΈΠ΄Π°Ρ‚ΡŒ освобоТдСния Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ. - **НСдостаточная Π³ΠΈΠ±ΠΊΠΎΡΡ‚ΡŒ:** ΠΏΡ€ΠΈ слоТных Π·Π°Π΄Π°Ρ‡Π°Ρ… многопоточности использованиС `synchronized` ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚Π°Ρ‚ΡŒ нСэффСктивным, ΠΈ Ρ‚ΠΎΠ³Π΄Π° Π»ΡƒΡ‡ΡˆΠ΅ Ρ€Π°ΡΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π±ΠΎΠ»Π΅Π΅ соврСмСнныС ΠΈ Π³ΠΈΠ±ΠΊΠΈΠ΅ Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Ρ‹, Ρ‚Π°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ классы ΠΈΠ· ΠΏΠ°ΠΊΠ΅Ρ‚Π° `java.util.concurrent` (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, `ReentrantLock`). ## ЧастыС ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ ΠΈ ошибки ### ЧрСзмСрная синхронизация (Over-synchronization) **ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ°:** Бинхронизация всСго ΠΌΠ΅Ρ‚ΠΎΠ΄Π° ΠΈΠ»ΠΈ слишком большого объСма ΠΊΠΎΠ΄Π° ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠ½ΠΈΠ·ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΏΠΎΡ‚ΠΎΠΊΠΈ Π²Ρ‹Π½ΡƒΠΆΠ΄Π΅Π½Ρ‹ ΠΆΠ΄Π°Ρ‚ΡŒ доступа ΠΊ синхронизированным участкам, Π΄Π°ΠΆΠ΅ Ссли это Π½Π΅ трСбуСтся. **РСшСниС:** Π‘Π»Π΅Π΄ΡƒΠ΅Ρ‚ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚Ρƒ Ρ‡Π°ΡΡ‚ΡŒ ΠΊΠΎΠ΄Π°, которая Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ Π·Π°Ρ‰ΠΈΡ‚Ρ‹. ### Бинхронизация Π½Π° Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠΌ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π΅ **ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ°:** Если синхронизация происходит Π½Π° локальном ΠΈΠ»ΠΈ Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΌ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π΅, это Π½Π΅ Π·Π°Ρ‰ΠΈΡ‚ΠΈΡ‚ Π΄Π°Π½Π½Ρ‹Π΅, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с собствСнной ΠΊΠΎΠΏΠΈΠ΅ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. ```java public class Counter { private int count = 0; public void increment() { // ΠΠ΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Π°Ρ синхронизация Π½Π° локальном ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π΅ Object lock = new Object(); synchronized (lock) { count++; } } } ``` Π—Π΄Π΅ΡΡŒ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ создаСт собствСнный ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ `lock`, ΠΈ, ΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ, синхронизация Π½Π΅ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚. **РСшСниС:** Π‘ΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·Π°Ρ†ΠΈΡŽ Π½ΡƒΠΆΠ½ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ Π½Π° ΠΎΠ±Ρ‰Π΅ΠΌ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π΅ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, `this` ΠΈΠ»ΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠΌ ΠΎΠ±Ρ‰Π΅ΠΌ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π΅). ### Бинхронизация Π½Π° статичСских ΠΈ нСстатичСских ΠΌΠ΅Ρ‚ΠΎΠ΄Π°Ρ… **ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ°:** Если Π½Π΅ ΠΏΠΎΠ½ΠΈΠΌΠ°Ρ‚ΡŒ, ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€Ρ‹ для статичСских ΠΈ нСстатичСских ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ², ΠΌΠΎΠΆΠ½ΠΎ случайно ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΡΠΈΡ‚ΡƒΠ°Ρ†ΠΈΡŽ, ΠΊΠΎΠ³Π΄Π° доступ ΠΊ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌ Π±ΡƒΠ΄Π΅Ρ‚ синхронизирован Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ. ```java public class StaticSyncExample { private static int staticCount = 0; private int instanceCount = 0; public static synchronized void incrementStatic() { staticCount++; } public synchronized void incrementInstance() { instanceCount++; } } ``` Π—Π΄Π΅ΡΡŒ Π²Ρ‹Π·ΠΎΠ² `incrementStatic` синхронизируСтся Π½Π° классС `StaticSyncExample.class`, Π° `incrementInstance` β€” Π½Π° ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠΌ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π΅ класса. Π­Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ нСдоразумСниям Π² случаях, ΠΊΠΎΠ³Π΄Π° оТидаСтся ΠΎΠ΄ΠΈΠ½ ΠΈ Ρ‚ΠΎΡ‚ ΠΆΠ΅ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ для всСго ΠΊΠΎΠ΄Π°. Π•Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ```java public class Container { private static final List list = new ArrayList<>(); synchronized void addEntry(String s) { list.add(s) } } ``` Π—Π΄Π΅ΡΡŒ Ρƒ нас Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ°, Ссли Π±ΡƒΠ΄Π΅Ρ‚ 2+ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° класса `Container`, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΈΠ· Π½ΠΈΡ… Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π½Π° своСм ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π΅, Π° пСрСмСнная `list` Ρƒ нас статичСская ΠΈ Π΅Π΅ экзСмпляр СдинствСнный Π½Π° всю ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ **РСшСниС:** НуТно ΡƒΡ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ статичСскиС ΠΈ нСстатичСскиС ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ Ρ€Π°Π·Π½Ρ‹Π΅ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€Ρ‹. Π§Ρ‚ΠΎΠ±Ρ‹ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ вСсь класс (Π²ΠΊΠ»ΡŽΡ‡Π°Ρ ΠΊΠ°ΠΊ статичСскиС, Ρ‚Π°ΠΊ ΠΈ нСстатичСскиС Π΄Π°Π½Π½Ρ‹Π΅), ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠ±Ρ‰ΠΈΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ для синхронизации. ### ΠŸΡ€ΠΎΠΏΡƒΡΠΊ синхронизации для чтСния ΠΈ записи **ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ°:** Π Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ чтСния ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… Π±Π΅Π· синхронизации, Ρ‚ΠΎΠ³Π΄Π° ΠΊΠ°ΠΊ ΠΈΡ… запись синхронизирована, ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ нСпрСдсказуСмым Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°ΠΌ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ значСния ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΡ€ΠΎΡ‡ΠΈΡ‚Π°Π½Ρ‹ Π² нСконсистСнтном состоянии. ```java public class Counter { private int count = 0; public synchronized void increment() { count++; } // ΠΠ΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠ΅ Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ Π±Π΅Π· синхронизации public int getCount() { return count; } } ``` Π’ этом случаС Ρ€Π°Π·Π½Ρ‹Π΅ ΠΏΠΎΡ‚ΠΎΠΊΠΈ ΠΌΠΎΠ³ΡƒΡ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ count. *** ## ΠœΠ΅Ρ‚Π° информация **ΠžΠ±Π»Π°ΡΡ‚ΡŒ**:: [[../../meta/zero/00 Java Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°|00 Java Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°]] **Π ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒ**:: [[ΠœΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒ Π² Java]] **Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ**:: **Π‘ΠΎΠ·Π΄Π°Π½Π°**:: [[2024-10-09]] **Автор**:: ### Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Ρ‹ - ### Π”ΠΎΡ‡Π΅Ρ€Π½ΠΈΠ΅ Π·Π°ΠΌΠ΅Ρ‚ΠΊΠΈ