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

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

Жанры

Программирование на языке 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, позволяющий получить и установить максимальный размер очереди.

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

Вернуть невесту. Ловушка для попаданки

Ардова Алиса
1. Вернуть невесту
Любовные романы:
любовно-фантастические романы
8.49
рейтинг книги
Вернуть невесту. Ловушка для попаданки

Наследник

Шимохин Дмитрий
1. Старицкий
Приключения:
исторические приключения
5.00
рейтинг книги
Наследник

Путешественник по Изнанке

Билик Дмитрий Александрович
4. Бедовый
Фантастика:
юмористическое фэнтези
городское фэнтези
попаданцы
мистика
5.00
рейтинг книги
Путешественник по Изнанке

Барон диктует правила

Ренгач Евгений
4. Закон сильного
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Барон диктует правила

Ненаглядная жена его светлости

Зика Натаэль
Любовные романы:
любовно-фантастические романы
6.23
рейтинг книги
Ненаглядная жена его светлости

Император Пограничья 10

Астахов Евгений Евгеньевич
10. Император Пограничья
Фантастика:
городское фэнтези
аниме
фантастика: прочее
попаданцы
5.00
рейтинг книги
Император Пограничья 10

Санек

Седой Василий
1. Санек
Фантастика:
попаданцы
альтернативная история
4.00
рейтинг книги
Санек

Меченный смертью. Том 2

Юрич Валерий
2. Меченный смертью
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Меченный смертью. Том 2

Надуй щеки! Том 4

Вишневский Сергей Викторович
4. Чеболь за партой
Фантастика:
попаданцы
уся
дорама
5.00
рейтинг книги
Надуй щеки! Том 4

Двойник короля 19

Скабер Артемий
19. Двойник Короля
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Двойник короля 19

Дважды одаренный. Том II

Тарс Элиан
2. Дважды одаренный
Фантастика:
городское фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Дважды одаренный. Том II

Черный Маг Императора 11

Герда Александр
11. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Черный Маг Императора 11

Спасите меня, Кацураги-сан! Том 12

Аржанов Алексей
12. Токийский лекарь
Фантастика:
попаданцы
дорама
фэнтези
5.00
рейтинг книги
Спасите меня, Кацураги-сан! Том 12

Я еще граф. Книга #8

Дрейк Сириус
8. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Я еще граф. Книга #8