Čo treba urobiť, ak dvaja pracovníci súčasne pristupujú k rovnakým údajom?
sobes.tech AI
Odpoveď od AI
Je potrebné zabezpečiť vlákno-bezpečný prístup k údajom. Hlavné prístupy:
-
Zámky (Locks): Používajú sa na obmedzenie prístupu ku kritickým sekciám kódu. Len jedno vlákno môže vlastniť zámok v danom momente.
# Príklad s Mutex v Ruby require 'thread' $shared_data = 0 $mutex = Mutex.new def increment_data $mutex.lock # Získanie zámku begin # Kritická sekcia temp = $shared_data sleep(0.01) # Napodobnenie práce $shared_data = temp + 1 ensure $mutex.unlock # Uvoľnenie zámku end end threads = [] 10.times do threads << Thread.new { increment_data } end threads.each(&:join) puts $shared_data # Garantovane bude 10 -
Transakcie databáz: Ak sú údaje uložené v databáze, používajte transakcie pre atomické operácie. Úroveň izolácie transakcií určuje, ako sú viditeľné zmeny vykonané inými transakciami.
# Príklad v Rails s použitím ActiveRecord ActiveRecord::Base.transaction do # Všetky operácie v bloku sa vykonávajú atomicky user = User.find(user_id) user.balance -= amount order = Order.create!(user: user, amount: amount) user.save! # Ak niečo zlyhá, celá transakcia sa vráti end -
Atomické operácie: Niektoré jazyky a knižnice poskytujú atomické typy údajov alebo operácie, ktoré sú garantovane vykonané ako celok, bez možnosti prerušenia inými vláknami.
# Ruby nemá vstavané atomické typy pre ľubovoľné údaje, # ale niektoré operácie (napríklad priradenie) môžu byť atomické # pre jednoduché typy. Pre zložitejšie scenáre sú potrebné zámky. -
Optimistická kontrola súbehu: Namiesto zámkov majú každý záznam číslo revízie alebo časovú značku. Pri aktualizácii sa kontroluje, či sa záznam nezmenil od jeho čítania. Ak sa zmenil, operácia sa reštartuje.
# Príklad s ActiveRecord::Locking::Optimistic # Pridajte `lock_version` (integer) do vašej tabuľky class Product < ApplicationRecord # ... end product = Product.find(id) # Iné vlákno aktualizuje ten istý produkt... begin product.price += 10 product.save! # Vygeneruje ActiveRecord::StaleObjectError, ak sa zmenil lock_version rescue ActiveRecord::StaleObjectError # Spracovanie konfliktu, napríklad, opätovné načítanie a pokus retry end -
Posolové sprostredkovatelia / Fronty: Namiesto priameho prístupu k údajom, pracovníci posielajú správy sprostredkovateľovi (napríklad RabbitMQ, Sidekiq s Redisom). Spracovanie správ prebieha sekvenčne alebo v riadenom poradí, čo znižuje pravdepodobnosť konfliktov.
-
Použitie nemenných objektov: Ak sú údaje nemenné, súčasný prístup k nim je bezpečný, pretože žiadny pracovník ich nemôže zmeniť.
Výber prístupu alebo kombinácie prístupov závisí od typu údajov, požiadaviek na výkon a architektúry aplikácie. Vo webových aplikáciách na Ruby on Rails sa často používajú transakcie ActiveRecord a optimistické zámky pre údaje v databáze, zatiaľ čo pre spoločné zdroje v pamäti - Mutex. Pozadie úlohy (napríklad Sidekiq) zvyčajne spracovávajú správy z front, ktoré samy o sebe zabezpečujú určitú mieru usporiadania.