Чтение онлайн

на главную - закладки

Жанры

Программирование на языке Ruby
Шрифт:

 end

end

t1 = Thread.new(0) {|num| process_list(num) }

t2 = Thread.new(1) {|num| process_list(num) }

t3 = Thread.new(2) {|num| process_list(num) }

t1.join

t2.join

t3.join

count = 0

@hash.values.each {|v| count += v.size }

puts "Всего слов: #{count} " # Может быть напечатано 7 или 8!

Здесь имеется проблема. Если ваша система ведет себя примерно так же, как наша, то программа может напечатать одно из двух значений! В наших тестах с одинаковой вероятностью печаталось 7 или 8. Если слов и списков больше, то и разброс окажется более широким.

Попробуем исправить положение с помощью мьютекса, который будет контролировать доступ к разделяемому ресурсу. (Слово «mutex» — это сокращение от mutual exclusion, «взаимная блокировка».)

Обратимся к листингу 13.2. Библиотека

Mutex
позволяет создавать мьютексы и манипулировать ими. Мы можем захватить (lock) мьютекс перед доступом к хэшу и освободить (unlock) его по завершении операции.

Листинг 13.2. Программа индексирования с мьютексом

require 'thread.rb'

@list = []

@list[0]="shoes ships\nsealing-wax"

@list[1]="cabbages kings"

@list[2]="quarks\nships\ncabbages"

def hesitate

 sleep rand(0)

end

@hash = {}

@mutex = Mutex.new

def process_list(listnum)

 lnum = 0

 @list[listnum].each do |line|

words = line.chomp.split

words.each do |w|

hesitate

@mutex.lock

if @hash[w]

hesitate

@hash[w] += ["#{listnum}:#{lnum}"]

else

hesitate

@hash[w] = ["#{listnum}:#{lnum}"]

end

@mutex.unlock

end

lnum += 1

 end

end

t1 = Thread.new(0) {|num| process_list(num) }

t2 = Thread.new(1) {|num| process_list(num) }

t3 = Thread.new(2) {|num| process_list(num) }

t1.join

t2.join

t3.join

count = 0

@hash.values.each {|v| count += v.size }

puts "Всего слов: #{count} " # Всегда печатается 8!

Отметим, что помимо метода

lock
в классе
Mutex
есть также метод
try_lock
. Он отличается от
lock
тем, что если мьютекс уже захвачен другим потоком, то он не дожидается освобождения, а сразу возвращает
false
.

require 'thread'

mutex = Mutex.new

t1 = Thread.new { mutex.lock; sleep 30 }

sleep 1

t2 = Thread.new do

 if mutex.try_lock

puts "Захватил"

 else

puts "He сумел захватить" # Печатается немедленно.

 end

end

sleep 2

Эта возможность полезна, если поток не хочет приостанавливать выполнение. Есть также метод

synchronize
, который захватывает мьютекс, а потом автоматически освобождает его.

mutex = Mutex.new

mutex.synchronize do

 # Любой код, нуждающийся в защите...

end

Существует еще библиотека

mutex_m
, где определен модуль
Mutex_m
, который можно подмешивать к классу (или использовать для расширения объекта). У такого расширенного объекта будут все методы мьютекса, так что он сам может выступать в роли мьютекса.

require 'mutex_m'

class MyClass

 include Mutex_m

 # Теперь любой объект класса MyClass может вызывать

 # методы lock, unlock, synchronize...

 # Внешние объекты также могут вызывать эти

 # методы для объекта MyClass.

end

13.2.3. Предопределенные классы синхронизированных очередей

В библиотеке

thread.rb
есть пара классов, которые иногда бывают полезны. Класс
Queue
реализует безопасную относительно потоков очередь, доступ к обоим концам которой синхронизирован. Это означает, что разные потоки могут, ничего не опасаясь, работать с такой очередью. Класс
SizedQueue
отличается от предыдущего тем, что позволяет ограничить размер очереди (число элементов в ней).

Оба класса имеют практически один и тот же набор методов, поскольку

SizedQueue
наследует
Queue
. Правда, в подклассе определен еще акцессор max, позволяющий получить и установить максимальный размер очереди.

Поделиться:
Популярные книги

Искушение чародея (сборник)

Булычев Кир
Фантастика:
научная фантастика
космическая фантастика
6.20
рейтинг книги
Искушение чародея (сборник)

Кир Булычев. Собрание сочинений в 18 томах. Т.9

Булычев Кир
Собрания сочинений
Фантастика:
альтернативная история
6.00
рейтинг книги
Кир Булычев. Собрание сочинений в 18 томах. Т.9

Паралогии

Липовецкий Марк Наумович
Научная библиотека
Научно-образовательная:
культурология
5.00
рейтинг книги
Паралогии

Поварское искусство

Зеленко П. М.
Дом и Семья:
кулинария
6.25
рейтинг книги
Поварское искусство

Ржавый Рыцарь и Пистолетов

Мельникова Ирина Александровна
Любовные романы:
остросюжетные любовные романы
7.94
рейтинг книги
Ржавый Рыцарь и Пистолетов

Американская фантастика

Гаррисон Гарри
Библиотека литературы США
Фантастика:
научная фантастика
7.00
рейтинг книги
Американская фантастика

Магическая сделка

Звездная Елена
3. Долина Драконов
Фантастика:
фэнтези
6.84
рейтинг книги
Магическая сделка

Ореховый посох

Скотт Роберт
1. Eldarn Trilogy
Фантастика:
фэнтези
6.25
рейтинг книги
Ореховый посох

Герда

Веркин Эдуард Николаевич
Детские:
детская проза
5.00
рейтинг книги
Герда

Бастард

Осадчук Алексей Витальевич
1. Последняя жизнь
Фантастика:
фэнтези
героическая фантастика
попаданцы
5.86
рейтинг книги
Бастард

Лондонские поля

Эмис Мартин
Интеллектуальный бестселлер. Читает весь мир.
Проза:
современная проза
7.11
рейтинг книги
Лондонские поля

Среди пуль

Проханов Александр Андреевич
Проза:
современная проза
6.25
рейтинг книги
Среди пуль

Царица амазонок

Фортье Энн
The Big Book
Проза:
современная проза
8.33
рейтинг книги
Царица амазонок

Газлайтер. Том 39

Володин Григорий Григорьевич
39. История Телепата
Фантастика:
боевая фантастика
юмористическая фантастика
аниме
попаданцы
6.25
рейтинг книги
Газлайтер. Том 39