Студопедия

КАТЕГОРИИ:

АстрономияБиологияГеографияДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРиторикаСоциологияСпортСтроительствоТехнологияФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника


Класс ReaderWriterLock




Очень часто встречается проблема синхронизации потоков, известная как проблема «множественного чтения и одиночной записи» (multiple-reader/single-writer). Эта проблема возникает, когда произвольное число потоков пытается получить доступ к общему ресурсу. Одни потоки (записывающие) хотят изменить содержимое данных, другие (считывающие) — только считать данные. Синхронизация необходима по четырем причинам:

1. Когда один поток записывает данные, остальным потокам нельзя их изменять;

2. когда один поток записывает данные, остальным потокам нельзя их считывать;

3. когда один поток считывает данные, остальные потоки не должны изменять их;

4. когда один поток считывает данные, остальные потоки также могут считывать их.

 

FCL предоставляет класс ReaderWriterLock, инкапсулирующий эти четыре правила. Можно создать экземпляр этого класса и вызывать методы для установки и освобождения блокировки. У ReaderWriterLock нет статических членов, но есть несколько экземплярных методов и свойств. Обычно, подходя к этой теме, я описываю, как использовать такую блокировку в приложениях, но сейчас я этого сделать не могу, порекомендовать ее использовать могу только врагу. Как вы увидите далее, этот класс создает массу проблем.

Во-первых, производительность только входа и выхода из блокировки ужасно низкая. Она неудовлетворительна, даже если нет конкурирующих за блокировку потоков. Мои измерения показали, что вход и выход в блокировку с использованием класса ReaderWriterLock выполняется примерно в пять раз медленнее, чем при помощи класса Monitor.

Во-вторых, когда поток завершает запись, из всех ожидающих доступа потоков эта блокировка отдает приоритет считывающим, что приводит к исключительно медленной работе записывающих потоков. Обычно класс ReaderWriterLock используют, когда мало записывающих, но много считывающих потоков. В конце концов, если бы к ресурсу обращались только считывающие потоки, его не нужно было бы блокировать, а если обращаются только записывающие, то нужно использовать взаимоисключающую блокировку, например блокировку синхронизации (которой можно управлять при помощи класса Monitor). Так что если используется класс ReaderWriterLock и есть ожидающие своей очереди записывающие потоки, нужно отдавать приоритет им. Я знаю несколько человек, которые пытались использовать класс ReaderWriterLock, но из-за того, что он отдает приоритет считывающим потокам, записывающие потоки надолго блокировались и очень долго не могли выполнить свою задачу.

В-третьих, класс ReaderWriterLock поддерживает рекурсию. То есть вошедший в блокировку и потом выходящий из нее поток должен быть одним и тем же потоком. Многие разработчики считают это преимуществом — я считаю это ошибкой. Все чаще возникают ситуации, когда один поток входит в блокировку и запускает операцию, обращающуюся к каким-то данным, а затем другой поток завершает эту операцию с данными и выходит из блокировки. Особенно часто это встречается в асинхронной модели программирования, описанной в главе 23. Блокировки, поддерживающие рекурсию, такие как ReaderWriterLock и Monitor, не поддерживают асинхронное программирование.

 


Поделиться:

Дата добавления: 2015-04-21; просмотров: 116; Мы поможем в написании вашей работы!; Нарушение авторских прав





lektsii.com - Лекции.Ком - 2014-2024 год. (0.006 сек.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав
Главная страница Случайная страница Контакты