அணு செயல்பாடுகளின் தோற்றத்திற்கான முன்நிபந்தனைகள்

அணு செயல்பாடுகள் எவ்வாறு செயல்படுகின்றன என்பதைப் புரிந்துகொள்ள இந்த எடுத்துக்காட்டைப் பார்ப்போம்:

public class Counter {
    int count;

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

எங்களிடம் ஒரு நூல் இருக்கும்போது, ​​​​எல்லாமே சிறப்பாக செயல்படுகின்றன, ஆனால் மல்டித்ரெடிங்கைச் சேர்த்தால், தவறான முடிவுகளைப் பெறுகிறோம், மேலும் அனைத்துமே அதிகரிப்பு செயல்பாடு ஒரு செயல்பாடு அல்ல, ஆனால் மூன்று: தற்போதைய மதிப்பைப் பெறுவதற்கான கோரிக்கைஎண்ணிக்கை, பின்னர் அதை 1 ஆல் கூட்டி மீண்டும் எழுதவும்எண்ணிக்கை.

இரண்டு திரிகள் ஒரு மாறியை அதிகரிக்க விரும்பினால், நீங்கள் பெரும்பாலும் தரவை இழப்பீர்கள். அதாவது, இரண்டு நூல்களும் 100 ஐப் பெறுகின்றன, இதன் விளைவாக, இரண்டும் எதிர்பார்க்கப்படும் மதிப்பு 102 க்கு பதிலாக 101 ஐ எழுதும்.

மற்றும் அதை எவ்வாறு தீர்ப்பது? நீங்கள் பூட்டுகளைப் பயன்படுத்த வேண்டும். ஒத்திசைக்கப்பட்ட திறவுச்சொல் இந்தச் சிக்கலைத் தீர்க்க உதவுகிறது, இதைப் பயன்படுத்துவது ஒரு நேரத்தில் ஒரு நூல் முறையை அணுகும் என்பதற்கு உத்தரவாதம் அளிக்கிறது.

public class SynchronizedCounterWithLock {
    private volatile int count;

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

கூடுதலாக, நீங்கள் கொந்தளிப்பான முக்கிய சொல்லைச் சேர்க்க வேண்டும் , இது நூல்களுக்கு இடையே உள்ள குறிப்புகளின் சரியான தெரிவுநிலையை உறுதி செய்கிறது. அவரது வேலையை மேலே மதிப்பாய்வு செய்துள்ளோம்.

ஆனால் இன்னும் குறைபாடுகள் உள்ளன. மிகப் பெரியது செயல்திறன், அந்த நேரத்தில் பல இழைகள் பூட்டைப் பெற முயற்சிக்கும் மற்றும் எழுதும் வாய்ப்பைப் பெறும்போது, ​​மீதமுள்ள இழைகள் நூல் வெளியிடப்படும் வரை தடுக்கப்படும் அல்லது இடைநிறுத்தப்படும்.

இந்த செயல்முறைகள், தடுப்பது, மற்றொரு நிலைக்கு மாறுதல் ஆகியவை கணினி செயல்திறனுக்கு மிகவும் விலை உயர்ந்தவை.

அணு செயல்பாடுகள்

இந்த அல்காரிதம் ஒப்பீடு மற்றும் இடமாற்று (CAS, compare-and-swap, இது தரவு ஒருமைப்பாட்டை உறுதிசெய்கிறது மற்றும் அவற்றில் ஏற்கனவே அதிக அளவு ஆராய்ச்சி உள்ளது) போன்ற குறைந்த-நிலை இயந்திர வழிமுறைகளைப் பயன்படுத்துகிறது.

ஒரு பொதுவான CAS செயல்பாடு மூன்று செயல்களில் செயல்படுகிறது:

  • வேலைக்கான நினைவக இடம் (எம்)
  • ஒரு மாறியின் தற்போதைய எதிர்பார்க்கப்படும் மதிப்பு (A).
  • புதிய மதிப்பு (B) அமைக்க வேண்டும்

CAS ஆனது M க்கு B ஆக மாற்றுகிறது, ஆனால் M இன் மதிப்பு A க்கு சமமாக இருந்தால் மட்டுமே, இல்லையெனில் எந்த நடவடிக்கையும் எடுக்கப்படாது.

முதல் மற்றும் இரண்டாவது நிகழ்வுகளில், M இன் மதிப்பு திரும்பப் பெறப்படும். இதன் மூலம் மதிப்பைப் பெறுதல், மதிப்பை ஒப்பிட்டுப் பார்த்தல் மற்றும் புதுப்பித்தல் ஆகிய மூன்று படிகளை இணைக்க முடியும். இது அனைத்தும் இயந்திர மட்டத்தில் ஒரு செயல்பாடாக மாறும்.

மல்டி-த்ரெட் செய்யப்பட்ட பயன்பாடு ஒரு மாறியை அணுகி, அதைப் புதுப்பிக்க முயற்சித்து, CAS பயன்படுத்தப்படும் தருணத்தில், த்ரெட்களில் ஒன்று அதைப் பெற்று அதைப் புதுப்பிக்க முடியும். ஆனால் பூட்டுகளைப் போலல்லாமல், மற்ற த்ரெட்கள் மதிப்பைப் புதுப்பிக்க முடியாமல் பிழைகளைப் பெறும். பின்னர் அவர்கள் மேலும் வேலைக்குச் செல்வார்கள், மேலும் இந்த வகை வேலைகளில் மாறுதல் முற்றிலும் விலக்கப்பட்டுள்ளது.

இந்த வழக்கில், CAS செயல்பாடு வெற்றிகரமாக வேலை செய்யாத சூழ்நிலையை நாம் கையாள வேண்டும் என்ற உண்மையின் காரணமாக தர்க்கம் மிகவும் கடினமாகிறது. செயல்பாடு வெற்றிபெறும் வரை அது நகராமல் இருக்க, குறியீட்டை மாதிரியாக்குவோம்.

அணு வகைகளின் அறிமுகம்

int வகையின் எளிமையான மாறிக்கு ஒத்திசைவை அமைக்க வேண்டிய சூழ்நிலையை நீங்கள் சந்தித்திருக்கிறீர்களா ?

நாம் ஏற்கனவே உள்ளடக்கிய முதல் வழி, ஆவியாகும் + ஒத்திசைக்கப்பட்டவை . ஆனால் சிறப்பு அணு* வகுப்புகளும் உள்ளன.

நாம் CAS ஐப் பயன்படுத்தினால், முதல் முறையுடன் ஒப்பிடும்போது செயல்பாடுகள் வேகமாகச் செயல்படும். மேலும், எங்களிடம் மதிப்பு மற்றும் அதிகரிப்பு மற்றும் குறைப்பு செயல்பாடுகளைச் சேர்ப்பதற்கான சிறப்பு மற்றும் மிகவும் வசதியான முறைகள் உள்ளன.

AtomicBoolean , AtomicInteger , AtomicLong , AtomicIntegerArray , AtomicLongArray ஆகியவை அணுவாக செயல்படும் வகுப்புகள். அவர்களுடனான வேலையை கீழே பகுப்பாய்வு செய்வோம்.

அணு முழு எண்

AtomicInteger வகுப்பு , நீட்டிக்கப்பட்ட அணு செயல்பாடுகளை வழங்குவதோடு, அணுவாகவும் படிக்கவும் எழுதவும் கூடிய ஒரு முழு எண்ணின் மீது செயல்பாடுகளை வழங்குகிறது .

மாறிகளைப் படிப்பது மற்றும் எழுதுவது போன்ற வேலை செய்யும் முறைகளைப் பெற்று அமைக்கிறது .

அதாவது, "நடக்கும்-முன்" நாம் முன்பு பேசிய அதே மாறியின் அடுத்தடுத்த ரசீதுகளுடன். அணு ஒப்பீட்டு முறை இந்த நினைவக நிலைத்தன்மை அம்சங்களையும் கொண்டுள்ளது.

ஒரு புதிய மதிப்பை வழங்கும் அனைத்து செயல்பாடுகளும் அணுவாகச் செய்யப்படுகின்றன:

int addAndGet (int டெல்டா) தற்போதைய மதிப்பில் ஒரு குறிப்பிட்ட மதிப்பைச் சேர்க்கிறது.
பூலியன் compareAndSet (எதிர்பார்க்கப்படும் எண்ணாக, புதுப்பிப்பு எண்ணாக) தற்போதைய மதிப்பு எதிர்பார்க்கப்படும் மதிப்புடன் பொருந்தினால், கொடுக்கப்பட்ட புதுப்பிக்கப்பட்ட மதிப்பிற்கு மதிப்பை அமைக்கிறது.
int decrementAndGet() தற்போதைய மதிப்பை ஒன்று குறைக்கிறது.
int getAndAdd(int delta) கொடுக்கப்பட்ட மதிப்பை தற்போதைய மதிப்புடன் சேர்க்கிறது.
int getAndDecrement() தற்போதைய மதிப்பை ஒன்று குறைக்கிறது.
int getAndIncrement() தற்போதைய மதிப்பை ஒன்று அதிகரிக்கிறது.
int getAndSet (int newValue) கொடுக்கப்பட்ட மதிப்பை அமைத்து பழைய மதிப்பை வழங்கும்.
int incrementAndGet() தற்போதைய மதிப்பை ஒன்று அதிகரிக்கிறது.
lazySet (int newValue) இறுதியாக கொடுக்கப்பட்ட மதிப்பை அமைக்கவும்.
பூலியன் பலவீனமான CompareAndSet (எதிர்பார்க்கப்பட்டது, புதுப்பிப்பு எண்ணாக) தற்போதைய மதிப்பு எதிர்பார்க்கப்படும் மதிப்புடன் பொருந்தினால், கொடுக்கப்பட்ட புதுப்பிக்கப்பட்ட மதிப்பிற்கு மதிப்பை அமைக்கிறது.

உதாரணமாக:

ExecutorService executor = Executors.newFixedThreadPool(5);
IntStream.range(0, 50).forEach(i -> executor.submit(atomicInteger::incrementAndGet));
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.HOURS);

System.out.println(atomicInteger.get()); // prints 50