Мьютекс (mutex, от "MUTual EXclusion") — это примитив синхронизации, который обеспечивает эксклюзивный доступ к общему ресурсу в многопоточной среде.
Мьютекс работает по принципу замка:
require 'thread'
mutex = Mutex.new
shared_resource = 0
threads = 10.times.map do
Thread.new do
mutex.synchronize do
# Критическая секция
shared_resource += 1
end
end
end
threads.each(&:join)
puts shared_resource # Гарантированно 10
Изменение общих данных:
Доступ к внешним ресурсам:
Обеспечение атомарности:
mutex = Mutex.new
mutex.lock
begin
# работа с ресурсом
ensure
mutex.unlock
end
r_mutex = Mutex.new
r_mutex.lock
r_mutex.lock # Не приведет к deadlock в рекурсивном мьютексе
cv = ConditionVariable.new
mutex = Mutex.new
resource_ready = false
# Поток-потребитель
Thread.new do
mutex.synchronize do
cv.wait(mutex) until resource_ready
puts "Resource is ready!"
end
end
# Поток-производитель
Thread.new do
mutex.synchronize do
resource_ready = true
cv.signal
end
end
mutex_a = Mutex.new
mutex_b = Mutex.new
Thread.new do
mutex_a.lock
sleep 0.1
mutex_b.lock # Блокируется
end
Thread.new do
mutex_b.lock
mutex_a.lock # Блокируется
end
Решение: Всегда блокировать мьютексы в одинаковом порядке
# Один поток постоянно захватывает мьютекс
while true
mutex.synchronize do
# Долгая операция
end
end
Решение: Использовать таймауты или fair locks
# Без мьютекса
counter = 0
10.times.map do
Thread.new do
1000.times { counter += 1 }
end
end.each(&:join)
puts counter # Может быть меньше 10000
Thread-safe структуры:
require 'thread'
queue = Queue.new
Атомарные операции:
require 'atomic'
atomic = Atomic.new(0)
atomic.update { |v| v + 1 }
Акторная модель (Celluloid, Concurrent-Ruby)
Мьютексы в Ruby:
Основные правила:
Помните: