Sobes.tech
Middle

Koje metode postoje za borbu sa kolizijama?

sobes.tech АИ

Одговор од АИ

Kolizija ili sukob javlja se prilikom spajanja promena iz različitih grana ili kada više procesa/vlakana menja iste podatke.

Metode za rešavanje kolizija zavise od njihove prirode:

  1. Upravljanje verzijama (npr. Git):

    • Ručno rešavanje: Git označava delove koda sa konfliktima. Programer ručno uređuje fajlove, birajući željene promene.
    • Korišćenje alata za spajanje: Vizuelni alati pomažu u poređenju i spajanju promena liniju po liniju.
    • Rebasing: Premestanje commit-ova iz jedne grane na drugu radi stvaranja linearnije istorije. Može zahtevati rešavanje konflikata za svaki commit.
    • Strategije spajanja (Merge Strategies): Git nudi različite strategije (recursive, ours, theirs) za automatsko ili poluautomatsko rešavanje određenih tipova konflikata.
    • Česta spajanja/rebasing: Smanjuju verovatnoću pojave složenih konflikata.
    // Primer konfliktnog koda u Git-u, koji treba ručno rešiti
    func updateData() {
        // Logika ažuriranja podataka
    <<<<<<< HEAD
        let newValue = "Vrednost iz grane BranchA"
    =======
        let newValue = "Vrednost iz grane BranchB"
    >>>>>>> feature/branchB
        print("Ažuriranje sa: \(newValue)")
    }
    
  2. U višestrukom/višeprocesnom okruženju (konkurentan pristup resursima):

    • Zaključavanja (Locks/Mutexes): Dozvoljavaju samo jednom niti da dobije ekskluzivni pristup kritičnom delu koda u bilo kom trenutku.
      import Foundation
      
      let mutex = NSLock() // Kreiranje mutexa
      
      func performOperation() {
          mutex.lock() // Zauzimanje zaključavanja
          // Kritični odeljak: kod koji može izazvati koliziju pri paralelnom pristupu
          print("Izvršavanje sigurne operacije")
          mutex.unlock() // Oslobađanje zaključavanja
      }
      
    • Atomske operacije: Garantuju da se operacije izvršavaju potpuno ili nikako, bez prekida od strane drugih niti.
    • Redovi (Queues, na primer GCD): Izvršavanje zadataka na sekvencijalnim redovima garantuje da pristup zajedničkim resursima ide putem jednog toka.
      import Foundation
      
      let serialQueue = DispatchQueue(label: "com.example.mySerialQueue")
      
      func updateSharedData() {
          serialQueue.async {
              // Pristup zajedničkim podacima samo iz ove redove
              print("Ažuriranje zajedničkih podataka asinhrono")
          }
      }
      
    • Korišćenje konkurentnih redova sa barijerama (Concurrent Queues with Barriers): Omogućavaju više niti da izvršavaju operacije čitanja paralelno, ali ih blokiraju za operacije pisanja.
      import Foundation
      
      let concurrentQueue = DispatchQueue(label: "com.example.myConcurrentQueue", attributes: .concurrent)
      var sharedArray = [Int]()
      
      func addValue(_ value: Int) {
          concurrentQueue.async(flags: .barrier) {
              // Operacija pisanja - izvršava se isključivo
              sharedArray.append(value)
              print("Dodata \(value)")
          }
      }
      
      func readArray() {
          concurrentQueue.async {
              // Operacija čitanja - može se izvršavati paralelno
              print("Trenutni niz: \(sharedArray)")
          }
      }
      
    • Atomske operacije: Niskonivojske operacije koje garantuju atomarnost (na primer, korišćenjem OSAtomic* funkcija ili C++11 atomics).
    • Transakciona memorija (Software Transactional Memory - STM): Visok nivo, koji omogućava grupisanje serije operacija u transakciju, koja ili uspešno izvršava ili se u potpunosti vrati nazad.

Izbor metode zavisi od konteksta i tipa kolizije.