synchronized β€” это ΠΎΠ΄ΠΈΠ½ ΠΈΠ· ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹Ρ… ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠΎΠ² Π² Java для управлСния ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒΡŽ ΠΈ обСспСчСния бСзопасности ΠΏΡ€ΠΈ доступС ΠΊ раздСляСмым рСсурсам. Π­Ρ‚ΠΎΡ‚ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΠΈΡ‚ΡŒ доступ ΠΊ критичСским сСкциям ΠΊΠΎΠ΄Π°, Ρ‚Π΅ΠΌ самым прСдотвращая состояния Π³ΠΎΠ½ΠΊΠΈ (race conditions).

Как Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ synchronized
Synchronized ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒΡΡ ΠΊ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°ΠΌ ΠΈΠ»ΠΈ Π±Π»ΠΎΠΊΠ°ΠΌ ΠΊΠΎΠ΄Π°. Когда ΠΏΠΎΡ‚ΠΎΠΊ Π²Ρ…ΠΎΠ΄ΠΈΡ‚ Π² ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΈΠ»ΠΈ Π±Π»ΠΎΠΊ, ΠΏΠΎΠΌΠ΅Ρ‡Π΅Π½Π½Ρ‹ΠΉ synchronized, ΠΎΠ½ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ (lock) Π½Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, связанный с этим ΠΊΠΎΠ΄ΠΎΠΌ. Π”Ρ€ΡƒΠ³ΠΈΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠΈ Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ доступ ΠΊ этому ΠΊΠΎΠ΄Ρƒ Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ освобоТдСн. Π­Ρ‚ΠΎ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚, Ρ‡Ρ‚ΠΎ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½ ΠΏΠΎΡ‚ΠΎΠΊ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ Π΄Π°Π½Π½Ρ‹ΠΉ ΠΊΠΎΠ΄.

Π’ этом ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅, synchronized Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ increment ΠΈ getCount Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ нСсколькими ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ, прСдотвращая Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Ρ‹Π΅ обновлСния ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ count.

public class Counter {
    private int count = 0;
 
    public synchronized void increment() {
        count++;
    }
 
    public synchronized int getCount() {
        return count;
    }
}

Иногда ΡƒΠ΄ΠΎΠ±Π½Π΅Π΅ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π½Π΅ вСсь ΠΌΠ΅Ρ‚ΠΎΠ΄, Π° Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π΅Π³ΠΎ Ρ‡Π°ΡΡ‚ΡŒ. Π’ этом случаС ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π±Π»ΠΎΠΊ synchronized:

public void increment() {
    synchronized (this) {
        count++;
    }
}

ΠžΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΠΈ

  • ΠœΠΎΠ½ΠΈΡ‚ΠΎΡ€Ρ‹ привязаны ΠΊ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌ, Π° Π½Π΅ ΠΊ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°ΠΌ. Если Π²Ρ‹ синхронизируСтС ΠΌΠ΅Ρ‚ΠΎΠ΄ экзСмпляра (instance method), Ρ‚ΠΎ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΎΠΌ являСтся Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ (this). Если ΠΌΠ΅Ρ‚ΠΎΠ΄ статичСский, Ρ‚ΠΎ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΎΠΌ выступаСт сам класс (ClassName.class).
  • Π‘Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ ΠΌΠΎΠ³ΡƒΡ‚ привСсти ΠΊ Π²Π·Π°ΠΈΠΌΠ½ΠΎΠΉ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ΅ (deadlock), Ссли Π΄Π²Π° ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΏΡ‹Ρ‚Π°ΡŽΡ‚ΡΡ Π·Π°Ρ…Π²Π°Ρ‚ΠΈΡ‚ΡŒ Π΄Ρ€ΡƒΠ³ Ρƒ Π΄Ρ€ΡƒΠ³Π° ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€Ρ‹ Π² Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠΌ порядкС.

ΠžΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΡ

  • Бинхронизация сниТаСт ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΏΠΎΡ‚ΠΎΠΊΠΈ Π²Ρ‹Π½ΡƒΠΆΠ΄Π΅Π½Ρ‹ ΠΎΠΆΠΈΠ΄Π°Ρ‚ΡŒ освобоТдСния Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ.
  • НСдостаточная Π³ΠΈΠ±ΠΊΠΎΡΡ‚ΡŒ: ΠΏΡ€ΠΈ слоТных Π·Π°Π΄Π°Ρ‡Π°Ρ… многопоточности использованиС synchronized ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚Π°Ρ‚ΡŒ нСэффСктивным, ΠΈ Ρ‚ΠΎΠ³Π΄Π° Π»ΡƒΡ‡ΡˆΠ΅ Ρ€Π°ΡΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π±ΠΎΠ»Π΅Π΅ соврСмСнныС ΠΈ Π³ΠΈΠ±ΠΊΠΈΠ΅ Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Ρ‹, Ρ‚Π°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ классы ΠΈΠ· ΠΏΠ°ΠΊΠ΅Ρ‚Π° java.util.concurrent (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ReentrantLock).

ЧастыС ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ ΠΈ ошибки

ЧрСзмСрная синхронизация (Over-synchronization)

ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ°: Бинхронизация всСго ΠΌΠ΅Ρ‚ΠΎΠ΄Π° ΠΈΠ»ΠΈ слишком большого объСма ΠΊΠΎΠ΄Π° ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠ½ΠΈΠ·ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΏΠΎΡ‚ΠΎΠΊΠΈ Π²Ρ‹Π½ΡƒΠΆΠ΄Π΅Π½Ρ‹ ΠΆΠ΄Π°Ρ‚ΡŒ доступа ΠΊ синхронизированным участкам, Π΄Π°ΠΆΠ΅ Ссли это Π½Π΅ трСбуСтся.

РСшСниС: Π‘Π»Π΅Π΄ΡƒΠ΅Ρ‚ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚Ρƒ Ρ‡Π°ΡΡ‚ΡŒ ΠΊΠΎΠ΄Π°, которая Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ Π·Π°Ρ‰ΠΈΡ‚Ρ‹.

Бинхронизация Π½Π° Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠΌ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π΅

ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ°: Если синхронизация происходит Π½Π° локальном ΠΈΠ»ΠΈ Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΌ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π΅, это Π½Π΅ Π·Π°Ρ‰ΠΈΡ‚ΠΈΡ‚ Π΄Π°Π½Π½Ρ‹Π΅, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с собствСнной ΠΊΠΎΠΏΠΈΠ΅ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°.

public class Counter {
    private int count = 0;
 
    public void increment() {
        // ΠΠ΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Π°Ρ синхронизация Π½Π° локальном ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π΅
        Object lock = new Object();
        synchronized (lock) {
            count++;
        }
    }
}

Π—Π΄Π΅ΡΡŒ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ создаСт собствСнный ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ lock, ΠΈ, ΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ, синхронизация Π½Π΅ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚.

РСшСниС: Π‘ΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·Π°Ρ†ΠΈΡŽ Π½ΡƒΠΆΠ½ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ Π½Π° ΠΎΠ±Ρ‰Π΅ΠΌ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π΅ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, this ΠΈΠ»ΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠΌ ΠΎΠ±Ρ‰Π΅ΠΌ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π΅).

Бинхронизация Π½Π° статичСских ΠΈ нСстатичСских ΠΌΠ΅Ρ‚ΠΎΠ΄Π°Ρ…

ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ°: Если Π½Π΅ ΠΏΠΎΠ½ΠΈΠΌΠ°Ρ‚ΡŒ, ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€Ρ‹ для статичСских ΠΈ нСстатичСских ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ², ΠΌΠΎΠΆΠ½ΠΎ случайно ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΡΠΈΡ‚ΡƒΠ°Ρ†ΠΈΡŽ, ΠΊΠΎΠ³Π΄Π° доступ ΠΊ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌ Π±ΡƒΠ΄Π΅Ρ‚ синхронизирован Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ.

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 β€” Π½Π° ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠΌ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π΅ класса. Π­Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ нСдоразумСниям Π² случаях, ΠΊΠΎΠ³Π΄Π° оТидаСтся ΠΎΠ΄ΠΈΠ½ ΠΈ Ρ‚ΠΎΡ‚ ΠΆΠ΅ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ для всСго ΠΊΠΎΠ΄Π°.

Π•Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ ΠΏΡ€ΠΈΠΌΠ΅Ρ€

public class Container {
	private static final List<String> list = new ArrayList<>();
 
	synchronized void addEntry(String s) {
		list.add(s)
	}
}

Π—Π΄Π΅ΡΡŒ Ρƒ нас Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ°, Ссли Π±ΡƒΠ΄Π΅Ρ‚ 2+ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° класса Container, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΈΠ· Π½ΠΈΡ… Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π½Π° своСм ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π΅, Π° пСрСмСнная list Ρƒ нас статичСская ΠΈ Π΅Π΅ экзСмпляр СдинствСнный Π½Π° всю ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ

РСшСниС: НуТно ΡƒΡ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ статичСскиС ΠΈ нСстатичСскиС ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ Ρ€Π°Π·Π½Ρ‹Π΅ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€Ρ‹. Π§Ρ‚ΠΎΠ±Ρ‹ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ вСсь класс (Π²ΠΊΠ»ΡŽΡ‡Π°Ρ ΠΊΠ°ΠΊ статичСскиС, Ρ‚Π°ΠΊ ΠΈ нСстатичСскиС Π΄Π°Π½Π½Ρ‹Π΅), ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠ±Ρ‰ΠΈΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ для синхронизации.

ΠŸΡ€ΠΎΠΏΡƒΡΠΊ синхронизации для чтСния ΠΈ записи

ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ°: Π Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ чтСния ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… Π±Π΅Π· синхронизации, Ρ‚ΠΎΠ³Π΄Π° ΠΊΠ°ΠΊ ΠΈΡ… запись синхронизирована, ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ нСпрСдсказуСмым Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°ΠΌ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ значСния ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΡ€ΠΎΡ‡ΠΈΡ‚Π°Π½Ρ‹ Π² нСконсистСнтном состоянии.

public class Counter {
    private int count = 0;
 
    public synchronized void increment() {
        count++;
    }
 
    // ΠΠ΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠ΅ Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ Π±Π΅Π· синхронизации
    public int getCount() {
        return count;
    }
}

Π’ этом случаС Ρ€Π°Π·Π½Ρ‹Π΅ ΠΏΠΎΡ‚ΠΎΠΊΠΈ ΠΌΠΎΠ³ΡƒΡ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ count.


ΠœΠ΅Ρ‚Π° информация

ΠžΠ±Π»Π°ΡΡ‚ΡŒ:: 00 Java Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°
Π ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒ:: ΠœΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒ Π² Java
Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ::
Π‘ΠΎΠ·Π΄Π°Π½Π°:: 2024-10-09
Автор::

Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Ρ‹

Π”ΠΎΡ‡Π΅Ρ€Π½ΠΈΠ΅ Π·Π°ΠΌΠ΅Ρ‚ΠΊΠΈ