Реалізація потокової архітектури “читач / письменник” в Visual C # (Sharp)

Потокового я архітектур а читач / письменник заснований а н а ідеї, чт про в т о час, когд а оди н пото до виконуваної т операци ю читання, а друго ї пото до такж е хоче т считат ь т е ж е дані , Т о почому у б и ем у н е дозволить ь це Н про есл і оди н пото до хоче т виконають ь операци ю записи, т о тольк про це т пото до Може т делат ь це Іншим і словами, досту п до даних д м дл я читанням я можу т розділять ь кіль про потоків, н про дл я запис і досту п до данни м предоставляетс я исключительн про одному у потоку

У NE T реалізований-клас з SystemThreadingReaderWriterLock, воно містить ї функ-нальних ь читач / письменник Це т клас з подобе н клас у Monitor в тому, чт про о н надається сезон т засобів про дл я управлени я доступів м до даних, н о н е визначає, до каки м данни м осуществляетс я доступ Клас з ReaderWriterLock імее т кіль про методо в і властивостей, сами е важливі е и з котори х перерахований и в табл 131

Таблиця 131Основні методи класуReaderWriterLock

Методи

Опис

AcquireReaderLock()

Отримує блокування читача Блокування читача можуть отримувати кілька потоків одночасно

AcquireWriterLock()

Отримує блокування письменника Тільки один потік мет утримувати блокування письменника

DowngradeFromWriterLock()

Перетворює блокування письменника в блокування читать Використання цього методу дозволяє уникнути послідовного виклику методів ReleaseWriterLock () І AcquireReaderLock ()

UpgradeToWriterLock()

Перетворює блокування читача в блокування писати Використання цього методу дозволяє уникнути послідовного виклику методів ReleaseReaderLock () І AcquireWriterLock ()

ReleaseLock()

Звільняє всі блокування, незалежно від того, скільки було виконано викликів на отримання блоковок читача чи письменника

ReleaseReaderLock()

Зменшує на одиницю значення рахунку блокування отримувача Щоб повністю звільнити блокування читель, необхідно, щоб кількість викликів методу ReleaseReaderLock () було дорівнює кількості виклик методу AcquireReaderLock)

ReleaseWriterLock()

Зменшує на одиницю значення рахунку блокування Пателя Щоб повністю звільнити блокування піселя, необхідно, щоб кількість викликів методу ReleaseWriterLock () було дорівнює кількості виклик методу AcquireWriterLock ()

Тепер ь розглянь м примі р фрезеруван і коллекци і чотирма я потоками: трьом я читачам і і одні м письменником У приклад е стратегічних і іспользуетс я мето д Threadsieepo, щоб и можн про був про бачити, каки м образо м потік і читачі я і пі – Сател я взаємодію т дру г з одним

using SystemThreading

ReaderWriterLock rwlock = new ReaderWriterLock()

List&ltint&gt elements = new List&ltint&gt() elementsAdd(10)

elementsAdd(20)

Thread threadl = new Thread(

() =&gt {

ThreadSleep(lOOO) ConsoleWriteLine(

&quotThread 1 waiting for read lock&quot) rwlockAcquireReaderLock(-l) ConsoleWriteLine(&quotThread 1 has read lock&quot) foreach (int item in elements) {

ConsoleWriteLine(&quotThread 1 Item(&quot +

item + &quot)&quot)

ThreadSleep(1000)

&gt&nbsp

})

ConsoleWriteLine(

&quotThread 1 releasing read lock&quot)

rwlockReleaseLock()

Thread thread2 = new Thread(

О => {

ThreadSleep(1250) ConsoleWriteLine(

&quotThread 2 waiting for read lock&quot) rwlockAcquireReaderLock(-l) ConsoleWriteLine(&quotThread 2 has read lock&quot) foreach (int item in elements) {

ConsoleWriteLine(&quotThread 2 Item (&quot +

item + &quot) &quot)

ThreadSleep(lOOO)

&gt&nbsp

ConsoleWriteLine(

&quotThread 2 releasing read lock&quot)

rwlock ReleaseI&gtock()

})    •

Thread thread3 = new Threadl

0  =&gt  {

ThreadSleep(1750) ConsoleWriteLine(

&quotThread 3 waiting for read lock&quot) rwlockAcquireReaderLock(-1) ConsoleWriteLine(&quotThread 3 has read lock&quot) foreach (int item in elements) {

ConsoleWriteLine(&quotThread 3 Item (&quot +

item + &quot) &quot) ThreadSleep(1000)

&gt&nbsp

ConsoleWriteLine(

&quotThread 3 releasing read lock&quot)

rwlockReleaseLockO

})

Thread thread4 = new Thread(

0  =&gt  {

ThreadSleep(1500) ConsoleWriteLine(

&quotThread 4 waiting for write lock&quot) rwlockAcquireWriterLock(-1) ConsoleWriteLine(&quotThread 4 has write Lock&quot) elementsAdd(30)

ConsoleWriteLine(

&quotThread 4 releasing write lock&quot)

rwlockReleaseliock()

})

threadlStart() thread2Start() threadsStart() thread4Start()

Жирним шрифтом в попередньому коді виділені всі звернення до реалізації класу читача / письменника NET На відміну від ключового слова lock і типу Monitor,

для типу ReaderWriterLock створюється екземпляр, який спільно використовується потоками

Методам для отримання блокування читача і письменника передається параметр -1, що означає, що метод повинен чекати, поки не буде отримана блокування Як параметр методу може передаватися позитивне значення, вказане тайм-аут в мілісекундах, по закінченню якого, якщо блокування не була отримана, метод повертає управління викликає потоку При ісполованіі тайм-ауту, перш ніж намагатися маніпулювати розділяються кодом, потрібно перевірити властивості IsReaderLockHeld або IsWriterLockHeld, щоб переконатися в тому, що блокування була отримана Після отримання блокування отримувача потоки читачів обробляють елементи колекції в циклі

ПРИМІТКА

Даний приклад, здається, нарешті правило, що свідчить утримувати блокування якомога короткий час, т к в ньому блокування утримується під час обробки ЕЛЕНТ в циклі У випадку з реалізацією читача / письменника ми маємо унікальну суацію в тому, що він призначається для маніпулювання даними, які в оовном тільки зчитуються Це означає, що більшу частину часу колективні дані будуть вважатися доступними тільки для читання А для рідкісних і коротких іервалов часу, коли в колективні дані виконується запис, очікування поту момент-другий не є нічим серйозним Використовувати блокування читати / письменника для даних, в основному не є тільки для читання, немає сенсу У таких ситуаціях слід використовувати підхід з типом Monitor, як було описано в попередньому розділі

Даний приклад демонструє обробку даних, призначених в основному для читання, т к в ньому використовуються три потоку для зчитування і один для запису Важливо, щоб під час утримування блокування читання не виконувалося операцій запису Дана реалізація читача / письменника призначена служити в якості керівництва, але не обовязково слідувати тільки методикою, викладеною в цьому роводстве

Результати виконання коду будуть наступними:

Thread 1 waiting for read lock / / Потік 1 очікує блокуванням читання Thread 1 has read lock / / Потік 1 отримав блокуванням читання Thread 1 Item (10)

Thread 2 waiting for read lock Thread 2 has read lock

Thread 2 Item (10)

Thread 4 waiting for write lock Thread 3 waiting for read lock Thread 1 Item (20)

Thread 2 Item (20)

Thread 1 releasing read lock / / Потік 1 звільняє блокування читання Thread 2 releasing read lock

Thread 4 has write lock

Thread 4 releasing write lock Thread 3 has read lock  Thread 3 Item (10)

Thread 3 Item (20)

Thread 3 Item (30)

Thread 3 releasing read lock

Даний висновок відображає таку послідовність подій:

1 Потік 1 запитує та отримує блокування тільки для читання

2 Потік 1 виводить перше число в колекції

3 Потік 2 запитує та отримує іншу блокування тільки для читання

4 Потік 2 виводить перше число в колекції

5 Потік 4 запрошувати блокування для запису і змушений чекати її

6 Потік 3 запрошувати блокування тільки для читання, але т к потік 4 запросив блокування для запису і очікує в черзі, то потік 3 теж ставиться в очедь На даному етапі потоки 3 і 4 стоять у черзі, чекаючи звільнення бліровок тільки для читання потоків 1 і 2

7 Потоки 1 і 2 виводять залишилися значення колекції

8 Потоки 1 і 2 звільняють блокування тільки для читання

9 Потік 4 отримує блокування для запису, а потік 3 продовжує очікувати

10&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp Потік 4 виконує запис в колекцію і звільняє блокування для запису

11&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp Потік 3 отримує блокування тільки для читання і обробляє в циклі ЕЛЕНТ колекції, включаючи елемент, доданий потоком 4

Зверніть увагу на те, як блокування читання / запису впорядковує последательность подій читання і запису, забезпечуючи, таким чином, сталість розділяється стану Але блокування читання / запису не може запобігти взаімоблокіровок, які можуть виникнути, якщо не дотримуватися належну остожность при написанні коду Блокування читання / запису дбає тільки про код, що застосовується для управління даними

Джерело: Гросс К С # 2008: Пер з англ – СПб: БХВ-Петербург, 2009 – 576 е: ил – (Самовчитель)

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*