Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
11
Добавлен:
27.03.2016
Размер:
38.91 Кб
Скачать

Лабораторна робота №8

Тема: Блокування на читання і запис.

ReaderWriterLock

Звичайно екземпляри типів потокобезопасны при рівнобіжних операціях читання, але не при рівнобіжних відновленнях, або рівнобіжному читанні і відновленні. Те ж саме справедливо для ресурсів, наприклад файлів. Якщо в основному виконується читання і тільки зрідка – запис, захист екземплярів таких типів простим ексклюзивним блокуванням для всіх режимів доступу може необґрунтовано обмежити паралелізм. Як приклад можна привести сервер додатків, у якому часто використовувані дані кэшируются в статичних полях для швидкого доступу. Клас ReaderWriterLock розроблений спеціально під такий сценарій роботи.

ReaderWriterLock надає окремі методи для блокування на читання і на запис – AcquireReaderLock і AcquireWriterLock. Обидва методи приймають аргумент-таймаут і генерують виключення ApplicationException, якщо цей таймаут минає (замість повернення false, як це роблять інші аналогічні методи, зв'язані з потоками). Таймаут може бути легко перевищений, якщо ресурс користується популярністю.

Блокування знімається за допомогою методів ReleaseReaderLock або ReleaseWriterLock. Ці методи підтримують вкладені блокування. Надається також метод ReleaseLock, що знімає усі вкладені блокування за один виклик. (Далі можна викликати RestoreLock для відновлення стану всіх блокувань, що передував викличу ReleaseLock – у наслідування поводженню Monitor.Wait).

Можна почати з блокування на читання викликом AcquireReaderLock, потім перетворити неї в блокування на запис, використовуючи UpgradeToWriterLock. Цей метод повертає cookie для наступного виклику DowngradeFromWriterLock. Така система дозволяє читачеві запитувати тимчасовий доступ для запису без необхідності повторного чекання в черзі.

У наступному прикладі стартують чотири потоки – один безупинно додає елементи в список, інший них видаляє, а два оставшихся постійно повідомляють про кількість елементів у списку. Перші два встановлюють блокування на запис, два що залишилися – тільки на читання. При кожнім блокуванні використовується таймаут у 10 секунд (обробка виключень у даному прикладі опущена для стислості).

class Program

{

static ReaderWriterLock rw = new ReaderWriterLock();

static List<int> items = new List<int>();

static Random rand = new Random();

static void Main(string[] args)

{

new Thread(delegate() { while (true) AppendItem(); }).Start();

new Thread(delegate() { while (true) RemoveItem(); }).Start();

new Thread(delegate() { while (true) WriteTotal(); }).Start();

new Thread(delegate() { while (true) WriteTotal(); }).Start();

}

static int GetRandNum(int max) { lock (rand) return rand.Next(max); }

static void WriteTotal()

{

rw.AcquireReaderLock(10000);

int tot = 0;

foreach (int i in items)

tot += i;

Console.WriteLine(tot);

rw.ReleaseReaderLock();

}

static void AppendItem()

{

rw.AcquireWriterLock(10000);

items.Add(GetRandNum(1000));

Thread.SpinWait(400);

rw.ReleaseWriterLock();

}

static void RemoveItem()

{

rw.AcquireWriterLock(10000);

if (items.Count > 0)

items.RemoveAt(GetRandNum(items.Count));

rw.ReleaseWriterLock();

}

}

Оскільки додавання елементів у список відбувається швидше, ніж видалення, у цьому прикладі в метод AppendItem доданий виклик SpinWait для збереження балансу.

Завдання: Розробити програму, в якый запускаэться 3 потоки + головний, відкривається текстовий файл, для головного потоку тільки на читання, а для робочих по черзі на запис (одночасно записує тільки 1 потік), для кожного робочого потоку доступ на запис відкривається тілки на 500мс, протягом яких він виводить в файл номер потоку, паралельно головний потік читає дані з файлу і одразу виводить на екран.

Соседние файлы в папке Semestr2