Программирование >>  Разработка устойчивых систем 

1 ... 175 176 177 [ 178 ] 179 180 181 ... 196


1nt mainO {

EvenChecker::test<GuardedEvenGenerator>(): } III:-

Обратите внимание: сохранять возвращаемое значение во временной переменной внутри nextValue() теперь не нужно. Обычно применение стражей сокращает объем программного кода и значительно снижает вероятность ощибок со стороны пользователей.

У щаблона Guard есть и другая интересная особенность: он позволяет безопасно манипулировать другими объектами-стражами. Например, второй объект Guard может использоваться для временного снятия блокировки:

: СП:TemperaryUnlоскing.срр Временное снятие блокировки с использованием другого стража. {L} ZThread

linclude zthread/Thread.h linclude zthread/Mutex.h linclude zthread/Guard.h using namespace ZThread:

class TemporaryUnlocking {

Mutex lock: public: void fO { Guard<Mutex> g(lock): Установление блокировки ... {

Guard<Mutex. UnlockedScope> h(g): Снятие блокировки ...

Установление блокировки

...

Снятие блокировки

int mainO {

TemporaryUnlocking t:

t.fO: } III:-

Объекты Guard также могут использоваться, чтобы попытаться установить блокировку в течение заданного промежутка времени:

: Cll:TimedLocking.cpp Попытки установления блокировки в течение заданного интервала. {L} ZThread

linclude zthread/Thread.h linclude zthread/Mutex.h

Thread::yield(): ++currentEven\/alue: return currentEvenValue:



int mainO {

TimedLocking t:

t.fO: } /:-

Если в данном примере не удастся установить блокировку в течение 500 мс, запускается исключение Timeout Exception.

Синхронизация целых классов

Библиотека ZThread содержит шаблон GuardedClass, предназначенный для автоматического создания синхронизированных оболочек для целых классов. Это подразумевает автоматическую зашиту каждой функции класса:

: Cll:SynchronizedClass.cpp {L} ZThread

#include zthread/GuardedClass.h using namespace ZThread:

class MyClass { public:

void funclO {}

void func2() {}

int mainO { MyClass a:

a.funclO: He синхронизируется a.func2(): He синхронизируется GuardedClass<MyClass> b(new MyClass): Синхронизированные вызовы, в любой момент времени доступ разрешен только одному программному потоку: b->funcl(): b->func2(): } III:-

объект а не синхронизирован, поэтому функции funcl() и func2() могут вызываться в любое время любым количеством потоков. Объект b зашишен шаблоном GuardedClass, а, следовательно, все его функции автоматически синхронизируются, и в любой момент времени для каждого объекта может вьшолняться только одна функция.

Шаблон GuardedClass устанавливает блокировку на уровне класса, что может отразиться на быстродействии. Если класс содержит несколько несвязанных функ-

Причем весьма существенно. Обычно бывает достаточно защитить лишь небольшую часть функции. Установка защиты в точке входа в функцию часто делает критическую секцию длиннее, чем требуется.

finclude zthread/Guard.h using namespace ZThread:

class TimedLocking {

Mutex lock: public:

void fO {

Guard<Mutex. TimedLockedScope<500> > g(lock): ...



ций, возможно, будет лучше организовать внутреннюю синхронизацию функций с разными блокировками. Но если вам приходится поступать подобным образом, это означает, что класс содержит группы данных, слабо связанные друг с другом. Подумайте, не стоит ли разбить такой класс на два.

Защита всех функций класса мутексами не гарантирует безопасности класса в плане работы с программными потоками. Чтобы обеспечить такую безопасность, необходимо тщательно продумать все потенциальные проблемы многопоточности.

Локальная память программных потоков

Второй способ решения проблем, обусловленных конфликтами доступа к общим ресурсам, заключается в отказе от совместного доступа как такового. В этом случае для одной переменной в каждом потоке, использующем объект, выделяется собственная копия памяти. Скажем, если пять программных потоков задействуют объект с переменной х, для х выделяется пять разных блоков памяти. К счастью, все операции создания и управления локальной памятью программных потоков в библиотеке ZThread осуществляются автоматически шаблоном ThreadLocal, как показано в примере:

: Cll:ThreadLocalVariables.cpp

Автоматическое выделение локальной памяти

для каждого программного потока.

{L} ZThread

linclude <iostream>

linclude zthread/Thread.h

linclude zthread/Mutex.h

linclude zthread/Guard.h

include Zthread/ThreadedExecutor.h

ii nclude zthread/Cancelable.h

linclude zthread/ThreadLocal .h

li nclude zthread/CountedPtr.h

using namespace ZThread:

using namespace std:

class ThreadLocalVariables : public Cancelable {

ThreadLocal<int> value:

bool canceled:

Mutex lock: public:

ThreadLocalVariablesO : canceled(false) { value.set(O):

void incrementO { value.set(value.get() + 1): } int getO { return value.getO: } void cancel О {

Guard<Mutex> g(lock):

canceled = true:

bool isCanceledO { Guard<Mutex> g(lock): return canceled:

class Accessor : public Runnable { int id:



1 ... 175 176 177 [ 178 ] 179 180 181 ... 196

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика