Race Condition mobil tətbiqlərdə: mahiyyəti, yaranma səbəbləri və qarşısının alınması yolları

Müəllif: IT Sectr Dərc olunub: 2026-03-18 Oxuma vaxtı: 10 dəq

Race Condition — çoxiplikli proqramlaşdırmada son nəticənin iplərin hansı ardıcıllıqla yerinə yetirilməsindən asılı olduğu vəziyyətdir. Oracle Java Tutorials (2024) sənədləşməsinə görə, yarış vəziyyəti sinxronizasiya olmadan ümumi resursa eyni vaxtda giriş zamanı yaranır. Düzgün mexanizmlər olmadan Race Condition məlumatların zədələnməsinə və mobil tətbiqlərdə təkrar olunmayan xətalarına gətirib çıxarır.

Əsas məqamlar

  • Race Condition — çoxiplikli koddakı qüsur, nəticənin icrası iplərin ardıcıllığından asılı olduqda
  • Yarış vəziyyəti ümumi resursa giriş zamanı sinxronizasiyanın olmaması ilə yaranır
  • Məlumat yarışı — dəyişənin eyni vaxtda yazılması və oxunması ilə bağlı Race Condition-ın alt növü
  • Mutex və semaforlar — mobil inkişafda yarış vəziyyətini aradan qaldırmaq üçün əsas vasitələr
  • Atom əməliyyatları icranın bölünməzliyinə zəmanət verir və iplərin yarışının qarşısını alır

Race Condition nədir?

Race Condition (yarış vəziyyəti) — çoxiplikli proqramda xəta, işin düzgünlüyü iplərin yerinə yetirilməsinin gözlənilməz ardıcıllığından asılı olduqda. İki və ya daha çox ip sinxronizasiya olmadan eyni vaxtda ümumi resursa müraciət etdikdə, resursun son vəziyyəti qeyri-müəyyən olur.

Mobil inkişafda Race Condition xüsusilə təhlükəlidir, çünki iplər prosessorun müxtəlif nüvələrində müxtəlif sürətlə yerinə yetirilə bilər. Tərtibatçı hansı ipin əməliyyatı birinci bitirəcəyini idarə edə bilməz — bunu əməliyyat sisteminin planlayıcısı həll edir. IBM-in tədqiqatına görə (Concurrency Bugs in Android, 2022), Android tətbiqlərindəki kritik xətaların təxminən 23%-i yarış vəziyyəti ilə bağlıdır.

Race Condition-un əsas xüsusiyyəti onun qeyri-deterministik olmasıdır. Eyni kod minlərlə dəfə xətasız işləyə bilər, sonra isə qəflətən çökə bilər. Bu diaqnostikanı xüsusilə çətin edir: xəta yalnız müəyyən şəraitdə — CPU yükü, aktiv iplərin sayı və planlaşdırma mərhələsində özünü göstərir.

Yarış vəziyyəti necə yaranır

Qeyri-atom əməliyyatlar

Race Condition ip qeyri-atom əməliyyat yerinə yetirdikdə yaranır — bir neçə addımdan ibarət ardıcıllıq, başqa bir ip tərəfindən kəsilə bilər. Məsələn, counter++ inkrementasiya əməliyyatı əslində üç addımdan ibarətdir: yaddaşdan dəyəri oxumaq, bir vahid artırmaq və geri yazmaq. İki ip bu addımları qarışıq şəkildə yerinə yetirərsə, nəticə səhv olacaq.

Sinxronizasiyanın olmaması

Yarış vəziyyətinin əsas səbəbi — paylaşılan məlumatlara giriş zamanı sinxronizasiyanın olmaması. Bir ip obyekti dəyişdirdikdə, digəri isə eyni anda onu oxuduqda, oxuma nəticəsi gözlənilməz olur. Android-də bu problem tətbiq komponentlərinin (Activity, Service, BroadcastReceiver) müxtəlif iplərdə yerinə yetirilə bilməsi ilə daha da kəskinləşir.

Korutinlərin düzgün istifadə edilməməsi

Müasir Kotlin ilə Android inkişafında Race Condition tez-tez korutinlərin düzgün istifadə edilməməsi ilə yaranır. İki korutin sinxronizasiya olmadan müxtəlif Dispatchers-lərdə ümumi vəziyyətlə işləyirsə, nəticə gözlənilməz olacaq. Bu xüsusilə Dispatchers.IO və Dispatchers.Main-in ümumi mutable obyektlərlə birləşdirilməsində tez-tez baş verir.

Kotlin kodunda Race Condition nümunəsi

Klassik məlumat yarışı nümunəsinə baxaq — bir neçə ipdən sayğacın inkrementasiyası. Sinxronizasiya olmadan son dəyər gözləniləndən az olacaq, çünki əməliyyatlar bir-birinin üzərinə qoyulur.

kotlin
class RaceCounter {
    private var counter = 0

    fun increment() {
        // Qeyri-atom əməliyyat — üç addım
        counter++  // oxuyur, artırır, yazır
    }

    fun getCount(): Int = counter
}

fun main() = runBlocking {
    val rc = RaceCounter()
    val jobs = List(1000) {
        launch(Dispatchers.Default) {
            rc.increment()
        }
    }
    jobs.forEach { it.join() }
    println(rc.getCount())  // 1000 gözləyirik, ~997 alırıq
}

Bu nümunədə 1000 korutin eyni vaxtda increment() çağırır. counter++ əməliyyatının qeyri-atom olması səbəbindən son dəyər demək olar ki, heç vaxt 1000-ə bərabər olmur. Hər işə salma fərqli nəticə verir — Race Condition-un klassik simptomu. Yarışda nə qədər çox ip iştirak edərsə, gözlənilən dəyərdən kənarlaşma bir o qədər çox olar.

Düzəliş — atom tipi və ya bloklanmanın istifadəsi. Kotlin-də bu tapşırıq üçün java.util.concurrent.atomic paketindən AtomicInteger uyğundur. O, oxuma-dəyişdirmə-yazma əməliyyatlarının prosessor səviyyəsində vahid bölünməz hərəkət kimi yerinə yetirilməsinə zəmanət verir.

kotlin
import java.util.concurrent.atomic.AtomicInteger

class SafeCounter {
    private val counter = AtomicInteger(0)

    fun increment() {
        counter.incrementAndGet()  // atom əməliyyatı
    }

    fun getCount(): Int = counter.get()
}

Yarış vəziyyətinin növləri

Məlumat yarışı (Data Race)

Məlumat yarışı — Race Condition-un ən geniş yayılmış növü. Bir ip dəyişənə məlumat yazdıqda, digəri isə eyni anda sinxronizasiya olmadan həmin dəyişəni oxuyanda və ya yazanda yaranır. Java Memory Model-də belə davranış qeyri-müəyyən sayılır — ip CPU səviyyəsində keşləmə səbəbindən aktual olmayan dəyər görə bilər.

Check-Then-Act

Check-Then-Act nümunəsi — ip şərti yoxlayır, sonra bu yoxlamaya əsasən hərəkət edir. Yoxlama və hərəkət arasında başqa bir ip vəziyyəti dəyişə bilər. Tipik nümunə: kolleksiyada elementin mövcudluğunu yoxlamaq və sonra onu silmək. Android-də bu tez-tez SharedPreferences və ya verilənlər bazası ilə işləyərkən baş verir.

Read-Modify-Write

Read-Modify-Write — ipin dəyəri oxuduğu, onu lokal yaddaşda dəyişdirdiyi və geri yazdığı vəziyyət. Oxuma və yazma arasında başqa bir ip orijinal dəyəri dəyişibsə, dəyişdirmə nəticəsi itiriləcək. Klassik nümunə — yuxarıda Kotlin kodunda göstərilən counter++ əməliyyatı.

Proqram transaksion yaddaşı (STM)

Software Transactional Memory (STM) — paylaşılan məlumatlar üzərində əməliyyatların verilənlər bazalarına bənzər şəkildə transaksiyalarda yerinə yetirildiyi yanaşma. İki transaksiya ziddiyyət təşkil edərsə, biri geri qaytarılır və təkrarlanır. Kotlin JVM üçün Multiverse STM kitabxanası mövcuddur, o, açıq bloklanmalar olmadan giriş ziddiyyətlərini avtomatik idarə edir. STM Android-də bir-biri ilə əlaqəli bir neçə obyektlə işləyərkən xüsusilə faydalıdır.

Android UI-də incə yarışlar

Race Condition-un xüsusi kateqoriyası — Activity-nin həyat dövrü ilə bağlı incə yarışlar (thin races). Tipik ssenari: fon ipi məlumat yükləməyi bitirir, lakin Activity artıq məhv edilib (ekranın döndərilməsi). Korutin mövcud olmayan View-i yeniləməyə çalışır və IllegalStateException ilə çökür. Həll yolu — Lifecycle Owner məhv edildikdə korutinləri avtomatik ləğv edən viewModelScope və Lifecycle-aware komponentlərindən istifadə etmək.

Race Condition-u necə aşkar etməli

Race Condition-un aşkarlanması çoxiplikli tətbiqlərin debug edilməsində ən çətin vəzifələrdən biridir. Standart testlər nadir hallarda yarış vəziyyətini üzə çıxarır, çünki o, yalnız zamanlamanın spesifik uyğunlaşması ilə özünü göstərir. Google-a görə (Android Testing Guide, 2023), Race Condition-ların təxminən 70%-i test mühitində deterministik icra ardıcıllığı səbəbindən vahid testlərlə aşkar edilmir.

Əsas aşkarlama üsulları ixtisaslaşmış alətləri əhatə edir. ThreadSanitizer (TSan) — Android NDK-ya quraşdırılmış dinamik analizator, yaddaşa bütün müraciətləri izləyir və sinxronizasiya olunmayan girişi aşkar edir. Java/Kotlin kodu üçün Google fon iplərindən UI ipinə qeyri-qanuni müraciətləri tutan StrictMode ilə birlikdə Android Studio Layout Inspector-dən istifadə etməyi tövsiyə edir.

Digər effektiv yanaşma — yük altında testlərin çoxsaylı icrası ilə Stress Testing. JetBrains-dən Lincheck çərçivəsi JVM-də rəqabətli məlumat strukturlarını test etmək üçün xüsusi olaraq hazırlanmışdır. O, müxtəlif əməliyyat permutasiyaları ilə ssenariləri avtomatik yaradır və hər bir halda nəticələrin düzgünlüyünü yoxlayır.

AlətPlatformaAnaliz növü
ThreadSanitizerAndroid NDKDinamik yaddaş analizi
Intel InspectorWindowsStatik + dinamik
LincheckJVM / KotlinStress testi
StrictModeAndroidİcra zamanı tutma

Race Condition-un qarşısının alınması üsulları

Atom dəyişənləri

Atom dəyişənləri (AtomicInteger, AtomicLong, AtomicReference) — tək əməliyyatlar üçün məlumat yarışını aradan qaldırmağın ən asan yolu. Onlar bloklanma olmadan atom şəkildə yerinə yetirilən aşağı səviyyəli CPU CAS (Compare-And-Swap) təlimatlarından istifadə edir. Bu, aşağı rəqabət ssenarilərində maksimum performans verir.

Bloklanmalar və Mutex

Mutex və bloklanmalar — mürəkkəb əməliyyatlar və kritik bölmələr üçün uyğun olan klassik sinxronizasiya mexanizmi. Kotlin korutinləri üçün ipi bloklamaq əvəzinə asmağı (suspending) dəstəkləyən kotlinx.coroutines kitabxanasından suspending Mutex istifadə olunur. Bu, ənənəvi bloklanmalara xas olan boş gözləmədən qaçmağa imkan verir.

Vəziyyətin izolyasiyası

Vəziyyətin izolyasiyası — hər bir ipin öz məlumat nüsxəsi ilə işlədiyi memarlıq yanaşması. Mobil inkişafda buna hər bir aktyorun öz vəziyyətinə sahib olduğu və digər aktyorlarla mesaj mübadiləsi apardığı Aktyor modeli ilə nail olunur. Kotlin Coroutines Channel və SendChannel vasitəsilə Aktyorun tətbiqini təmin edir ki, bu da Race Condition-u memarlıq səviyyəsində tamamilə aradan qaldırır.

Əlavə qorunma səviyyəsi — Immutability: paylaşılan məlumatlar prinsipcə dəyişməzdirsə, Race Condition hətta sinxronizasiya olmadan da qeyri-mümkün olur. Kotlin-də bunun üçün val sahələri olan data class və iplər arasında nəşr edildikdə strukturun dəyişməzliyinə zəmanət verən kotlinx.collections.immutable kolleksiyaları istifadə olunur.

Tez-tez verilən suallar

Race Condition və Data Race arasında nə fərq var?

Data Race — iki ipin eyni vaxtda eyni yaddaşa müraciət etdiyi və onlardan ən azı birinin yazma əməliyyatı yerinə yetirdiyi konkret Race Condition növüdür. Race Condition daha geniş anlayışdır, iplərin yerinə yetirilmə ardıcıllığından asılı olan istənilən xətaları, o cümlədən məntiqi yarış vəziyyətlərini əhatə edir.

Android-də Race Condition-u tamamilə aradan qaldırmaq mümkündürmü?

Tamamilə aradan qaldırmaq mümkün deyil, ancaq minimuma endirmək olar. Dəyişməz obyektlərdən (immutable), atom tiplərindən və tək iplikli dispetçerli korutinlərdən istifadə edin. ThreadSafety qaydası ilə Android Lint kimi statik analiz alətləri potensial yarışları kompilyasiya mərhələsində aşkar etməyə kömək edir.

Race Condition UI tətbiqlərində necə özünü göstərir?

UI tətbiqlərində Race Condition tez-tez ekranın titrəməsi, məlumatların səhv göstərilməsi və ya siyahının yenilənməsi zamanı çökmə kimi özünü göstərir. Tipik ssenari: fon ipi məlumatları yükləyir və adapteri yeniləyir, istifadəçi isə bu anda siyahını sürüşdürür — Adapter DataSet-ə eyni vaxtda giriş yaranır.

Volatile nədir və Race Condition-a kömək edirmi?

volatile dəyişikliklərin iplər arasında görünməsinə zəmanət verir — volatile dəyişənə yazma dərhal bütün iplərə görünür. Bununla belə, volatile Read-Modify-Write və Check-Then-Act problemini həll etmir, çünki mürəkkəb əməliyyatların atomluğunu təmin etmir. Belə ssenarilər üçün bloklanmalar və ya atom sinifləri lazımdır.

Kotlin Coroutines-də Race Condition klassik iplərdən nə ilə fərqlənir?

Kotlin Coroutines-də Race Condition korutin planlayıcısı səviyyəsində yaranır, ƏS ip planlayıcısı səviyyəsində deyil. Korutinlər asma (suspend) nöqtələrində keçid edə bilər ki, bu da yarış üçün əlavə imkanlar yaradır. kotlinx.coroutines.debug aləti və IntelliJ IDEA debugeri korutinlərin vəziyyətini izləməyə kömək edir.

Nəticə

  • Race Condition — çoxiplikli kodun xətası, nəticə iplərin gözlənilməz icra ardıcıllığından asılı olduqda
  • Data Race — yaddaşa yazma ilə eyni vaxtda sinxronizasiya olunmamış giriş zamanı yaranan yarış vəziyyətinin alt növü
  • Qeyri-atom əməliyyatlar (Read-Modify-Write, Check-Then-Act) — iplərin yarışının yaranmasının əsas səbəbi
  • ThreadSanitizer və Lincheck — test mərhələsində Race Condition-u aşkar etmək üçün effektiv alətlər
  • Atom dəyişənləri (AtomicInteger) — bloklanma olmadan tək əməliyyatları qorumağın optimal yolu
  • Mutex və Aktyor modeli — mürəkkəb kritik bölmələri qorumaq üçün memarlıq yanaşmaları
  • Vəziyyətin izolyasiyası dəyişməz obyektlər və tək iplikli dispetçerlər vasitəsilə Race Condition-u dizayn səviyyəsində tamamilə aradan qaldırır

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun