Sobes.tech
Middle

Խոսեք մրցակցության վիճակի (race condition) մասին և ինչպես կարելի է խուսափել այն բազմատող ծրագրերում։

sobes.tech AI

Պատասխան AI-ից

Անվտանգության վիճակը՝ դա բազմամյա համակարգի սխալն է, երբ ծրագրի կատարման արդյունքը կախված է տարբեր հոսքերի կողմից կոդի մասերի կատարման կարգից։ Դա տեղի է ունենում, երբ միաժամանակ մի քանի հոսք մուտք է գործում ընդհանուր փոփոխական ռեսուրսին առանց համապատասխան սինխրոնիզացիայի:

Java-ում ռիսկային վիճակը խուսափելու համար օգտագործվում են հետևյալ մոտեցումները:

  1. Սինխրոնիզացված մեթոդների և բլոկների օգտագործում՝

    class Counter {
        private int count = 0;
    
        // Սինխրոնիզացված մեթոդ
        public synchronized void increment() {
            count++;
        }
    
        // Սինխրոնիզացված բլոկ
        public void decrement() {
            synchronized (this) {
                count--;
            }
        }
    }
    

    synchronized բառը ապահովում է, որ միայն մեկ հոսք կարող է միաժամանակ կատարել սինխրոնիզացված կոդը տվյալ օբյեկտի համար (կամ դասի, եթե մեթոդը ստատիկ է):

  2. Lock դասի օգտագործում՝ java.util.concurrent.locks փաթեթից՝

    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    class SafeCounter {
        private int count = 0;
        private final Lock lock = new ReentrantLock();
    
        public void increment() {
            lock.lock(); // Բլոկավորման գրավում
            try {
                count++;
            } finally {
                lock.unlock(); // Բլոկավորման ազատում
            }
        }
    }
    

    Lock-ը ավելի ճկուն մեխանիզմներ է առաջարկում բլոկավորման համար՝ համեմատած synchronized-ի հետ:

  3. Ատոմարային փոփոխականների օգտագործում՝ java.util.concurrent.atomic փաթեթից՝

    import java.util.concurrent.atomic.AtomicInteger;
    
    class AtomicCounter {
        private AtomicInteger count = new AtomicInteger(0);
    
        public void increment() {
            count.incrementAndGet(); // Ատոմարային գործողություն
        }
    }
    

    Ատոմարային փոփոխականները ապահովում են գործողությունների ամբողջականություն՝ օրինակ, ավելացում, նվազեցում, որոնք կատարվում են որպես միավոր և չեն կարող խզվել այլ հոսքի կողմից:

  4. java.util.concurrent փաթեթից բեռնված հոսքային անվտանգ հավաքածուներ՝ օրինակ, ConcurrentHashMap, CopyOnWriteArrayList։ Այս հավաքածուները նախագծված են բազմահոսքային միջավայրում անվտանգ օգտագործման համար:

  5. Ընդհանուր փոփոխական վիճակի խուսափում՝ Եթե հնարավոր է, տվյալները, որոնք հասանելի են միաժամանակ մի քանի հոսքերին, պետք է լինեն անփոփոխ (immutable) կամ առանձնացվեն յուրաքանչյուր հոսքի համար:

  6. volatile-ի օգտագործում՝ volatile բառը ապահովում է փոփոխականի տեսանելիությունը բոլոր հոսքերին, բայց չի ապահովում գործողությունների ատոմայինությունը (բացառությամբ պարզ primitive տիպերի ընթերցում և գրառում, բացառությամբ long և double, ինչպես նաև հղումների): Այն օգտակար է այլ մեխանիզմների հետ համակցված կամ պարզ, անկախ գործողությունների համար:

    class VolatileFlag {
        volatile boolean flag = false; // Տեսանելիության ապահովում
    
        public void setFlag() {
            flag = true;
        }
    
        public boolean isFlag() {
            return flag;
        }
    }
    

Ընտրությունը կախված է կոնկրետ իրավիճակից և կատարման և կոդի բարդության պահանջներից։