Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ «Ѐилософия Java3Β». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 121

Автор Π‘Ρ€ΡŽΡ ЭккСль

Π₯отя try-finally Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ большСго объСма ΠΊΠΎΠ΄Π°, Ρ‡Π΅ΠΌ ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠ΅ слово synchronized, явноС использованиС ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Lock ΠΎΠ±Π»Π°Π΄Π°Π΅Ρ‚ своими прСимущСствами. ΠŸΡ€ΠΈ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΈΠΈ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ с ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹ΠΌ словом synchronized происходит ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, Π½ΠΎ Π²Ρ‹ Π½Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ°ΡŽΡ‰ΠΈΠ΅ дСйствия, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡΠΎΡ…Ρ€Π°Π½ΠΈΡ‚ΡŒ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠ΅ состояниС систСмы. ΠŸΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ с ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌΠΈ Lock ΠΌΠΎΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ всС Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΠ΅ Π² сСкции finally.

Π’ ΠΎΠ±Ρ‰Π΅ΠΌ случаС использованиС synchronized ΡƒΠΌΠ΅Π½ΡŒΡˆΠ°Π΅Ρ‚ объСм ΠΊΠΎΠ΄Π°, Π° Ρ‚Π°ΠΊΠΆΠ΅ Ρ€Π°Π΄ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎ сниТаСт Π²Π΅Ρ€ΠΎΡΡ‚Π½ΠΎΡΡ‚ΡŒ ошибки со стороны программиста, поэтому явныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ с ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌΠΈ Lock ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠΈ особых Π·Π°Π΄Π°Ρ‡. НапримСр, с ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹ΠΌ словом synchronized нСльзя ΠΏΠΎΠΏΡ‹Ρ‚Π°Ρ‚ΡŒΡΡ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ с Π½Π΅ΡƒΠ΄Π°Ρ‡Π½Ρ‹ΠΌ исходом ΠΈΠ»ΠΈ ΠΏΠΎΠΏΡ‹Ρ‚Π°Ρ‚ΡŒΡΡ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ Π² Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΊΠ° Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ с ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΡ‚ΠΊΠ°Π·ΠΎΠΌ β€” Π² ΠΏΠΎΠ΄ΠΎΠ±Π½Ρ‹Ρ… случаях приходится ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΡƒ concurrent:

//: concurrency/AttemptLocking java

// ΠžΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ Lock ΠΈΠ· Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ concurrent Π΄Π΅Π»Π°ΡŽΡ‚ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Ρ‹ΠΌΠΈ

// ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠΈ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ Π² Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ

import java.util.concurrent *;

import java util concurrent.locks.*;

public class AttemptLocking {

private ReentrantLock lock = new ReentrantLockO;

public void untimedO {

boolean captured = lock.tryLockO, try {

System.out printlnCtryLockO: " + captured); } finally {

if(captured)

lock unlockO;

}

}

public void timedO {

boolean captured = false; try {

captured = lock tryLock(2, TimeUnit SECONDS); } catch(InterruptedException e) {

throw new RuntimeException(e);

}

try {

System out println("tryLock(2. TimeUnit SECONDS): " +

captured),

} finally {

if(captured)

lock unlockO,

}

}

public static void main(String[] args) {

final AttemptLocking al = new AttemptLocking(),

al untimedO. // True -- Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ° доступна al timedO. // True -- Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ° доступна // Π’Π΅ΠΏΠ΅Ρ€ΡŒ создаСм ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΡƒΡŽ Π·Π°Π΄Π°Ρ‡Ρƒ для установлСния Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ new ThreadO {

{ setDaemon(true), } public void run() {

al lock lockO.

System.out printlnC'acquired");

}

} startO,

Thread yieldO, // Π”Π°Π΅ΠΌ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ 2-ΠΉ Π·Π°Π΄Π°Ρ‡Π΅ al untimedO; // False -- Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ° Π·Π°Ρ…Π²Π°Ρ‡Π΅Π½Π° Π·Π°Π΄Π°Ρ‡Π΅ΠΉ al.timedO. // False -- Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ° Π·Π°Ρ…Π²Π°Ρ‡Π΅Π½Π° Π·Π°Π΄Π°Ρ‡Π΅ΠΉ

}

} /* Output-tryLockO. true

tryLock(2, TimeUnit.SECONDS): true acquired

tryLockO false

tryLock(2, TimeUnit SECONDS)- false */// ~

Класс ReentrantLock Π΄Π΅Π»Π°Π΅Ρ‚ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΠΉ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΡƒ получСния Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ с ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΡ‚ΠΊΠ°Π·ΠΎΠΌ ΠΎΡ‚ Π½Π΅Π΅. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Ссли ΠΊΡ‚ΠΎ-Ρ‚ΠΎ ΡƒΠΆΠ΅ Π·Π°Ρ…Π²Π°Ρ‚ΠΈΠ» Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΎΡ‚ΠΊΠ°Π·Π°Ρ‚ΡŒΡΡ ΠΎΡ‚ своих Π½Π°ΠΌΠ΅Ρ€Π΅Π½ΠΈΠΉ (вмСсто Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π΄ΠΎΠΆΠΈΠ΄Π°Ρ‚ΡŒΡΡ Π΅Π΅ освобоТдСния). Π’ ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ timed() дСлаСтся ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠ° установлСния Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ, которая ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡŒΡΡ Π½Π΅ΡƒΠ΄Π°Ρ‡Π΅ΠΉ Ρ‡Π΅Ρ€Π΅Π· 2 сСкунды (ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° использованиС класса Java SE5 TimeUnit для опрСдСлСния Π΅Π΄ΠΈΠ½ΠΈΡ† Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ). Π’ main() ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Thread создаСтся Π² Π²ΠΈΠ΄Π΅ бСзымянного класса ΠΈ устанавливаСт Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ untimed() ΠΈ timed() ΠΌΠΎΠ³Π»ΠΈ с Ρ‡Π΅ΠΌ-Ρ‚ΠΎ ΠΊΠΎΠ½ΠΊΡƒΡ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ.

АтомарныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΈ ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠ΅ слово volatile

Π’ дискуссиях, посвящСнных ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΡƒ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² Π² Java, часто ΠΌΠΎΠΆΠ½ΠΎ ΡƒΡΠ»Ρ‹ΡˆΠ°Ρ‚ΡŒ Ρ‚Π°ΠΊΠΎΠ΅ ΡƒΡ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅: «АтомарныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π½Π΅ Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ синхронизации». Атомарная опСрация β€” это опСрация, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€Π΅Ρ€Π²Π°Ρ‚ΡŒ ΠΏΠ»Π°Π½ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² β€” Ссли ΠΎΠ½Π° начинаСтся, Ρ‚ΠΎ продолТаСтся Π΄ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ, Π±Π΅Π· возмоТности ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ контСкста (ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ выполнСния Π½Π° Π΄Ρ€ΡƒΠ³ΠΎΠΉ ΠΏΠΎΡ‚ΠΎΠΊ). НС ΠΏΠΎΠ»Π°Π³Π°ΠΉΡ‚Π΅ΡΡŒ Π½Π° Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½ΠΎΡΡ‚ΡŒ, ΠΎΠ½Π° Π½Π΅Π½Π°Π΄Π΅ΠΆΠ½Π° ΠΈ опасна β€” ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Π΅Π΅ вмСсто синхронизации Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² Ρ‚ΠΎΠΌ случаС, Ссли Π²Ρ‹ ΡΠ²Π»ΡΠ΅Ρ‚Π΅ΡΡŒ экспСртом Π² области синхронизации ΠΈΠ»ΠΈ, ΠΏΠΎ ΠΊΡ€Π°ΠΉΠ½Π΅ΠΉ ΠΌΠ΅Ρ€Π΅, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΏΠΎΠΌΠΎΡ‰ΡŒ ΠΎΡ‚ Ρ‚Π°ΠΊΠΎΠ³ΠΎ экспСрта.

АтомарныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΡƒΠΏΠΎΠΌΠΈΠ½Π°Π΅ΠΌΡ‹Π΅ Π² Ρ‚Π°ΠΊΠΈΡ… дискуссиях, Π²ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ Π² сСбя «простыС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈΒ» с ΠΏΡ€ΠΈΠΌΠΈΡ‚ΠΈΠ²Π½Ρ‹ΠΌΠΈ Ρ‚ΠΈΠΏΠ°ΠΌΠΈ, Π·Π° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ΠΌ long ΠΈ double.

Π§Ρ‚Π΅Π½ΠΈΠ΅ ΠΈ запись ΠΏΡ€ΠΈΠΌΠΈΡ‚ΠΈΠ²Π½Ρ‹Ρ… ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½Ρ‹Π΅ (Π½Π΅Π΄Π΅Π»ΠΈΠΌΡ‹Π΅) ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ. Π‘ Π΄Ρ€ΡƒΠ³ΠΎΠΉ стороны, JVM Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Π΅Ρ‚ΡΡ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ ΠΈ запись 64-разрядных Π²Π΅Π»ΠΈΡ‡ΠΈΠ½ (long ΠΈ double) Π² Π²ΠΈΠ΄Π΅ Π΄Π²ΡƒΡ… Ρ€Π°Π·Π΄Π΅Π»ΡŒΠ½Ρ‹Ρ… 32-разрядных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, с Π½Π΅Π½ΡƒΠ»Π΅Π²ΠΎΠΉ Π²Π΅Ρ€ΠΎΡΡ‚Π½ΠΎΡΡ‚ΡŒΡŽ ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ контСкста Π² Ρ…ΠΎΠ΄Π΅ чтСния ΠΈΠ»ΠΈ записи. Для достиТСния атомарности (ΠΏΡ€ΠΈ простом присваивании ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‚Π΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ) ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ Ρ‚ΠΈΠΏΡ‹ long ΠΈ double с ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΎΠΌ volatile (ΡƒΡ‡Ρ‚ΠΈΡ‚Π΅, Ρ‡Ρ‚ΠΎ Π΄ΠΎ Π²Ρ‹Ρ…ΠΎΠ΄Π° Java SE5 ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠ΅ слово volatile Π½Π΅ всСгда Ρ€Π°Π±ΠΎΡ‚Π°Π»ΠΎ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ). НСкоторыС Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ JVM ΠΌΠΎΠ³ΡƒΡ‚ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡ‚ΡŒ Π±ΠΎΠ»Π΅Π΅ ΡΠΈΠ»ΡŒΠ½Ρ‹Π΅ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΠΈ, Π½ΠΎ Π²Ρ‹ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΏΠΎΠ»Π°Π³Π°Ρ‚ΡŒΡΡ Π½Π° ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ΅Π½Π½ΠΎ-спСци-фичСскиС возмоТности.

Π’ многопроцСссорных систСмах (ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π² наши Π΄Π½ΠΈ прСдставлСны многоядСрными процСссорами, Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ нСсколькими процСсорами Π½Π° ΠΎΠ΄Π½ΠΎΠΌ Ρ‡ΠΈΠΏΠ΅) Π²ΠΈΠ΄ΠΈΠΌΠΎΡΡ‚ΡŒ (visibility) ΠΈΠ³Ρ€Π°Π΅Ρ‚ Π³ΠΎΡ€Π°Π·Π΄ΠΎ Π±ΠΎΠ»Π΅Π΅ Π²Π°ΠΆΠ½ΡƒΡŽ Ρ€ΠΎΠ»ΡŒ, Ρ‡Π΅ΠΌ Π² однопроцСссорных систСмах. ИзмСнСния, вносимыС ΠΎΠ΄Π½ΠΎΠΉ Π·Π°Π΄Π°Ρ‡Π΅ΠΉ, β€” Π΄Π°ΠΆΠ΅ Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½Ρ‹Π΅ Π² смыслС нСвозмоТности прСрывания β€” ΠΌΠΎΠ³ΡƒΡ‚ ΠΎΡΡ‚Π°Π²Π°Ρ‚ΡŒΡΡ Π½Π΅Π²ΠΈΠ΄ΠΈΠΌΡ‹ΠΌΠΈ для Π΄Ρ€ΡƒΠ³ΠΈΡ… Π·Π°Π΄Π°Ρ‡ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Ссли измСнСния Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ хранятся Π² локальном кэшС процСссора). Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Ρ€Π°Π·Π½Ρ‹Π΅ Π·Π°Π΄Π°Ρ‡ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎ-Ρ€Π°Π·Π½ΠΎΠΌΡƒ Π²ΠΎΡΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Ρ‚ΡŒ состояниС прилоТСния. ΠœΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ синхронизации обСспСчиваСт распространСниС видимости ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ, вносимых ΠΎΠ΄Π½ΠΎΠΉ Π·Π°Π΄Π°Ρ‡Π΅ΠΉ Π² многопроцСссорной систСмС, ΠΏΠΎ всСму ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡŽ. Π‘Π΅Π· синхронизации Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Ρ€Π°Π½Π΅Π΅ ΠΏΡ€Π΅Π΄ΡΠΊΠ°Π·Π°Ρ‚ΡŒ, ΠΊΠΎΠ³Π΄Π° ΠΈΠΌΠ΅Π½Π½ΠΎ измСнСния станут Π²ΠΈΠ΄ΠΈΠΌΡ‹ΠΌΠΈ.

ΠšΠ»ΡŽΡ‡Π΅Π²ΠΎΠ΅ слово volatile обСспСчиваСт Π²ΠΈΠ΄ΠΈΠΌΠΎΡΡ‚ΡŒ Π² Ρ€Π°ΠΌΠΊΠ°Ρ… прилоТСния. Если ΠΏΠΎΠ»Π΅ объявлСно ΠΊΠ°ΠΊ volatile, это ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ сразу ΠΆΠ΅ послС записи Π² ΠΏΠΎΠ»Π΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΡ‚Ρ€Π°ΠΆΠ΅Π½ΠΎ Π²ΠΎ всСх ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… опСрациях чтСния. Π£Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅ истинно Π΄Π°ΠΆΠ΅ ΠΏΡ€ΠΈ участии Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… кэшСй β€” поля volatile Π½Π΅ΠΌΠ΅Π΄Π»Π΅Π½Π½ΠΎ Π·Π°ΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‚ΡΡ Π² ΠΎΡΠ½ΠΎΠ²Π½ΡƒΡŽ ΠΏΠ°ΠΌΡΡ‚ΡŒ, ΠΈ дальнСйшСС Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ происходит ΠΈΠ· основной памяти.

Если слСпо ΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ†ΠΈΠΈ атомарности, ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄ getValue() Π² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ Π²Ρ€ΠΎΠ΄Π΅ Π±Ρ‹ ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚ этому описанию:

//: concurrency/AtomicityTest.java

import java.util.concurrent.*;

public class AtomicityTest implements Runnable { private int i = 0; public int getValueO { return i; } private synchronized void evenIncrement О { i++, i++. } public void run() { while(true)

evenlncrementO;

}

public static void mam(String[] args) {

ExecutorService exec = Executors newCachedThreadPoolО; AtomicityTest at = new AtomicityTest(); exec execute(at). while(true) {

int val = at.getValueO; if(val % 2 != 0) {

System.out.println(val), System.exit(0);

} /* Output

191583767

*///:-

Однако ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π½Π°Ρ…ΠΎΠ΄ΠΈΡ‚ Π½Π΅Ρ‡Π΅Ρ‚Π½Ρ‹Π΅ значСния ΠΈ Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ. Π₯отя return i ΠΈ являСтся Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠ΅ΠΉ, отсутствиС synchronized ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ‚ Ρ‡ΠΈΡ‚Π°Ρ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, ΠΊΠΎΠ³Π΄Π° ΠΎΠ½ находится Π² Π½Π΅ΡΡ‚Π°Π±ΠΈΠ»ΡŒΠ½ΠΎΠΌ ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½ΠΎΠΌ состоянии. Π’Π΄ΠΎΠ±Π°Π²ΠΎΠΊ пСрСмСнная i Π½Π΅ объявлСна ΠΊΠ°ΠΊ volatile, Π° это ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Ρ‚ ΠΊ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ°ΠΌ с Π²ΠΈΠ΄ΠΈΠΌΠΎΡΡ‚ΡŒΡŽ. Оба ΠΌΠ΅Ρ‚ΠΎΠ΄Π°, getValue() ΠΈ evenlncrement(), Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ ΠΎΠ±ΡŠΡΠ²Π»Π΅Π½Ρ‹ синхронизируСмыми. Волько экспСрты Π² области ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½Ρ‹Ρ… вычислСний ΠΌΠΎΠ³ΡƒΡ‚ ΠΏΡ‹Ρ‚Π°Ρ‚ΡŒΡΡ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΡŽ Π² ΠΏΠΎΠ΄ΠΎΠ±Π½Ρ‹Ρ… случаях.

Π’ качСствС Π²Ρ‚ΠΎΡ€ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° рассмотрим ΠΊΠΎΠ΅-Ρ‡Ρ‚ΠΎ Π΅Ρ‰Π΅ Π±ΠΎΠ»Π΅Π΅ простоС: класс, производящий сСрийныС Π½ΠΎΠΌΠ΅Ρ€Π°25. ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π· ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° nextSerialNum-ber() ΠΎΠ½ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅:

//: concurrency/SerialNumberGeneratorJava

public class SerialNumberGenerator {

private static volatile int serial Number = 0, public static int nextSerialNumberО {

return serialNumber++; // ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ Π½Π΅ являСтся ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎ-бСзопасной

}

} ///.-

ΠŸΡ€Π΅Π΄ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ сСбС класс Ρ‚Ρ€ΠΈΠ²ΠΈΠ°Π»ΡŒΠ½Π΅Π΅ SerialNumberGenerator вряд Π»ΠΈ ΠΌΠΎΠΆΠ½ΠΎ, ΠΈ Ссли Π²Ρ‹ Ρ€Π°Π½Π΅Π΅ Ρ€Π°Π±ΠΎΡ‚Π°Π»ΠΈ с языком Π‘++ ΠΈΠ»ΠΈ ΠΈΠΌΠ΅Π΅Ρ‚Π΅ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ Π½ΠΈΠ·ΠΊΠΎΡƒΡ€ΠΎΠ²Π½Π΅Π²Ρ‹Π΅ Π½Π°Π²Ρ‹ΠΊΠΈ, Ρ‚ΠΎ, Π²ΠΈΠ΄ΠΈΠΌΠΎ, ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚Π΅, Ρ‡Ρ‚ΠΎ опСрация ΠΈΠ½ΠΊΡ€Π΅ΠΌΠ΅Π½Ρ‚Π° Π±ΡƒΠ΄Π΅Ρ‚ Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½ΠΎΠΉ, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΈΠ½ΠΊΡ€Π΅ΠΌΠ΅Π½Ρ‚ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ рСализуСтся Π² Π²ΠΈΠ΄Π΅ ΠΎΠ΄Π½ΠΎΠΉ инструкции микропроцСссора. Однако Π² Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠΉ машинС Java ΠΈΠ½ΠΊΡ€Π΅ΠΌΠ΅Π½Ρ‚ Π½Π΅ являСтся Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½Ρ‹ΠΌ ΠΈ состоит ΠΈΠ· чтСния ΠΈ записи, соотвСтствСнно, ниша для ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ с ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ найдСтся Π΄Π°ΠΆΠ΅ Π² Ρ‚Π°ΠΊΠΎΠΉ простой ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅.

ПолС serialNumber объявлСно ΠΊΠ°ΠΊ volatile ΠΏΠΎΡ‚ΠΎΠΌΡƒ, Ρ‡Ρ‚ΠΎ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ ΠΎΠ±Π»Π°Π΄Π°Π΅Ρ‚ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΌ стСком ΠΈ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ Π² Π½Π΅ΠΌ ΠΊΠΎΠΏΠΈΠΈ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…. Если Π²Ρ‹ ΠΎΠ±ΡŠΡΠ²Π»ΡΠ΅Ρ‚Π΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ ΠΊΠ°ΠΊ volatile, Ρ‚ΠΎ Ρ‚Π΅ΠΌ самым ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚Π΅ компилятору Π½Π΅ ΠΏΡ€ΠΎΠ²ΠΎΠ΄ΠΈΡ‚ΡŒ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΡŽ, Π° это ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Ρ‚ ΠΊ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΡŽ чтСния ΠΈ записи, ΡƒΠ΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‰ΠΈΡ… ΠΏΠΎΠ»Π΅ Π² соотвСтствии с Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΌΠΈ Π΄Π°Π½Π½Ρ‹ΠΌΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠ°. ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ чтСния ΠΈ записи ΠΎΡΡƒΡ‰Π΅ΡΡ‚Π²Π»ΡΡŽΡ‚ΡΡ нСпосрСдствСнно с ΠΏΠ°ΠΌΡΡ‚ΡŒΡŽ Π±Π΅Π· ΠΊΡΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡ. ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, volatile Π½Π΅ позволяСт компилятору ΠΈΠ·ΠΌΠ΅Π½ΡΡ‚ΡŒ порядок ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΉ с Ρ†Π΅Π»ΡŒΡŽ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ. И всС ΠΆΠ΅ присутствиС volatile Π½Π΅ влияСт Π½Π° Ρ‚ΠΎΡ‚ Ρ„Π°ΠΊΡ‚, Ρ‡Ρ‚ΠΎ ΠΈΠ½ΠΊΡ€Π΅ΠΌΠ΅Π½Ρ‚ Π½Π΅ являСтся Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠ΅ΠΉ.

Для тСстирования Π½Π°ΠΌ понадобится мноТСство, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π½Π΅ ΠΏΠΎΡ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ ΠΏΠ΅Ρ€Π΅ΠΈΠ·Π±Ρ‹Ρ‚ΠΊΠ° памяти Π² Ρ‚ΠΎΠΌ случаС, Ссли ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ ΠΎΡ‚Π½ΠΈΠΌΠ΅Ρ‚ ΠΌΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ. ΠŸΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Ρ‹ΠΉ Π΄Π°Π»Π΅Π΅ класс CircularSet ΠΌΠ½ΠΎΠ³ΠΎΠΊΡ€Π°Ρ‚Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΏΠ°ΠΌΡΡ‚ΡŒ, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ хранятся Ρ†Π΅Π»Ρ‹Π΅ числа (int); прСдполагаСтся, Ρ‡Ρ‚ΠΎ ΠΊ Ρ‚ΠΎΠΌΡƒ ΠΌΠΎΠΌΠ΅Π½Ρ‚Ρƒ, ΠΊΠΎΠ³Π΄Π° запись Π² мноТСство начинаСтся ΠΏΠΎ Π½ΠΎΠ²ΠΎΠΌΡƒ ΠΊΡ€ΡƒΠ³Ρƒ, Π²Π΅Ρ€ΠΎΡΡ‚Π½ΠΎΡΡ‚ΡŒ ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚Π°

с пСрСзаписанными значСниями минимальна. ΠœΠ΅Ρ‚ΠΎΠ΄Ρ‹ add() ΠΈ contains() ΠΎΠ±ΡŠΡΠ²Π»Π΅Π½Ρ‹ ΠΊΠ°ΠΊ synchronized, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ ΠΊΠΎΠ»Π»ΠΈΠ·ΠΈΠΉ:

//: concurrency/SerialNumberChecker java // ΠšΠ°ΠΆΡƒΡ‰ΠΈΠ΅ΡΡ бСзопасными ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ с появлСниСм ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² // ΠΏΠ΅Ρ€Π΅ΡΡ‚Π°ΡŽΡ‚ Π±Ρ‹Ρ‚ΡŒ Ρ‚Π°ΠΊΠΎΠ²Ρ‹ΠΌΠΈ. // {Args- 4}

import java util.concurrent *;

// Reuses storage so we don't run out of memory: class CircularSet {

private int[] array: private int len; private int index = 0; public CircularSet(int size) { array = new int[size], len = size.

// Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅ΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π½Π΅ производится // классом SerialNumberGenerator for(int i =0; i < size; i++) array[i] = -1;

}

public synchronized void add(int i) { array[index] = i,

// Π’ΠΎΠ·Π²Ρ€Π°Ρ‚ индСкса ΠΊ Π½Π°Ρ‡Π°Π»Ρƒ с записью ΠΏΠΎΠ²Π΅Ρ€Ρ… старых Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ: index = ++index % len.

}

public synchronized boolean contains(int val) { for(int i = 0; i < len; i++)

if(array[i] == val) return true; return false;

public class SerialNumberChecker {

private static final int SIZE = 10; private static CircularSet serials =

new CircularSet(lOOO); private static ExecutorService exec =