Объектно-ориентированное программирование. Лекции 15 и...
Post on 20-Jan-2017
468 Views
Preview:
TRANSCRIPT
Условнаяпеременнаяпримитивсинхронизации,обеспечивающийблокированиеодногоилинесколькихпотоковдомоментапоступлениясигналаотдругогопотокаовыполнениинекоторогоусловияилидоистечениямаксимальногопромежуткавремениожидания.Условныепеременныеиспользуютсявместесассоциированныммьютексом иявляютсяэлементомнекоторыхвидовмониторов.
Монитор
thread
wait
thread
notifyAll
…
thread
wait
…
thread
wait
…
thread
wait
…
Условныепеременные <condition_variable>Example116_CondVariable1condition_variableтребуетотлюбогопотокапередожиданиемсначалавыполнитьstd::unique_lock
1. Долженбытьхотябыодинпоток,ожидающий,покакакое-тоусловиестанетистинным.Ожидающийпотокдолженсначалавыполнитьunique_lock.
2. Долженбытьхотябыодинпоток,сигнализирующийотом,чтоусловиесталоистинным.Сигналможетбытьпосланспомощьюnotify_one(),приэтомбудетразблокированодин(любой)потокизожидающих,илиnotify_all(),чторазблокируетвсеожидающиепотоки.
3. Ввидунекоторыхсложностейприсозданиипробуждающегоусловия,котороеможетбытьпредсказуемыхвмногопроцессорныхсистемах,могутпроисходитьложныепробуждения(spurious wakeup).Этоозначает,чтопотокможетбытьпробужден,дажееслиниктонесигнализировалусловнойпеременной.Поэтомунеобходимоещепроверять,вернолиусловиепробуждениеужепослето,какпотокбылпробужден.
ЗапускаемцепочкузаданийExample117_CondVariable2
Процесс1
Процесс2
ОжидаетусловнойПеременнойвследующемпотоке
Процесс3
ОжидаетусловнойПеременнойвследующемпотоке
ЗаконАмдалаДжинАмдал(Gene Amdahl)- одинизразработчиковвсемирноизвестнойсистемы IBM360в1967годупредложилформулу,отражающуюзависимостьускорениявычислений,достигаемогонамногопроцессорнойВС,какотчислапроцессоров,такиотсоотношениямеждупоследовательнойираспараллеливаемойчастямипрограммы.ПроблемарассматриваласьАмдаломисходяизположения,чтообъемрешаемой задачи(рабочаянагрузка- числовыполняемыхопераций)сизменением числапроцессоров,участвующихвеерешении, остаетсянеизменным.
Пустьf - доляопераций,которыедолжнывыполнятьсяпоследовательнооднимизпроцессорови1-f - доля,приходящаясянараспараллеливаемуючастьпрограммы.Тогдаускорение,котороеможетбытьполученонаВСиз n процессоров,посравнениюсоднопроцессорнымрешениемнебудетпревышатьвеличины:
S(n)=T(1)/T(n)=1/[f+(1-f)/n].
Например,еслиполовинаоперацийподлежитраспараллеливаниюна4машинах, тоускорениеравно:
S(4)=1/(0.5+0.5/4)=1.6т.е.Тольковполторараза!
Проблемаблокировок1. Взаимоблокировки(Deadlocks)2. Надежность— вдругвладелецблокировкипомрет?3. Performance◦ Параллелизмавкритическойсекциинет!◦ Владелецблокировкиможетбытьвытеснен
планировщиком
Неблокирующиеалгоритмы1. Безпрепятствий(Obstruction-Free)— потоксовершает
прогресс,еслиневстречаетпрепятствийсостороныдругихпотоков
2. Безблокировок(Lock-Free)— гарантируетсясистемныйпрогрессхотябыодногопотока
3. Безожидания(Wait-Free)— каждаяоперациявыполняетсязафиксированноечислошагов,независящееотдругихпотоков
АтомарныеоперацииАтомарностьозначаетнеделимостьоперации.Этозначит,чтониодинпотокнеможетувидетьпромежуточноесостояниеоперации,оналибовыполняется,либонет.
Напримероперация«++»неявляетсяатомарной:
int x = 0;
++x;
Транслируетсявассемблерныйкод,примернотак:
013C5595 mov eax,dword ptr [x]
013C5598 add eax,1
013C559B mov dword ptr [x],eax
АтомарныетипыC++#include<atomic>
std::atomic_bool //bool
std::atomic_char //char
std::atomic_schar //signed char
std::atomic_uchar //unsigned char
std::atomic_int //int
std::atomic_uint //unsigned int
std::atomic_short //short
std::atomic_ushort //unsigned short
std::atomic_long //long
std::atomic_ulong //unsigned long
std::atomic_llong //long long
std::atomic_ullong //unsigned long long
std::atomic_char16_t //char16_t
std::atomic_char32_t //char32_t
std::atomic_wchar_t //wchar_t
std::atomic_address //void*
CAS-операции1. CAS— compare-and-set,compare-and-
swap◦ bool compare_and_set(◦ int*адрес_переменной ,◦ int староезначение ,◦ int новоезначение)
2. ✔ Возвращает признакуспешностиоперации установки значения
3. ✔ Атомарнана уровнепроцессора
1. Являетсяаппаратнымпримитивом
2. Возможностьпродолжениязахватапримитивабезобязательногопереходаврежим«ожидания»
3. Меньшевероятностьвозникновенияблокировкииз-заболеемелкойоперации
4. Болеебыстрая
CASLoop— типичный паттернприменения1. ПрочитатьзначениеA изпеременнойV2. Взятькакое-тоновоезначениеB дляV3. ИспользоватьCASдляатомарногоизмененияV изA вB дотех
пор,покадругиепотокименяютзначениеV вовремяэтогопроцесса
Основныеоперацииload() //Прочитать текущее значение
store() //Установить новое значение
exchange() //Установить новое значение и вернуть предыдущее
compare_exchange_weak() // см. следующий слайд
compare_exchange_strong() // compare_exchange_weak в цикле
fetch_add() //Аналог оператора ++
fetch_or() //Аналог оператора --
is_lock_free() //Возвращает true, если операции на данном типе неблокирующие
Методatomic::compare_exchange_weakbool compare_exchange_weak( Ty& Exp, Ty Value)
Сравниваетзначениякоторыехранитсяв*this сExp.
• Еслизначенияравнытооперациязаменяетзначение,котораяхранитсяв*this наVal(*this=val),спомощьюоперацииread-modify-write.
• Еслизначениянеравны,тооперацияиспользуетзначение,котораяхранитсяв*this,чтобызаменитьExp (exp=this).
ПростойпримерExample120_CASSimple
1.class Counter {2.private:3. std::atomic_int value_a;4.public:5. Counter() : value_a(0) { }6. int get_a() {7. return value_a.load();8. }9. int increment_atomic() {10. int v = value_a.load();11. while (!value_a.compare_exchange_weak(v, v + 1));12. return value_a.load();13. }14.};
Потокобезопасный StackExample119_CASvoid push(const T& data)
{
node* new_node = new node(data, head.load());
while (!head.compare_exchange_weak(
new_node->next,
new_node));
}
Недостатки CAS1. CASзаставляетпотоки,которыееговызывают,
работатьвусловияхсоревнования(contention)2. Большеcontention =большебесполезныхциклов
процессора,тратапроцессорноговремени3. НаписаниекорректныхибыстрыхалгоритмовнаCAS
требуетспециальнойподготовки
LambdaExample121_LambdaЛямбда-выражениявC++— этократкаяформазаписианонимныхфункторов.
Например:
[](int _n){cout <<_n<<"";}
Соответствует:
class MyLambda{public:void operator ()(int _x)const {cout <<_x<<"";}
};
ЛямбдафункциимогутвозвращатьзначенияExample122_Lambda2Вслучае,есливлямбда-функциитолькоодиноператорreturnтотипзначенияможнонеуказывать.Еслинесколько,тонужноявноуказать.[] (int i) -> double
{
if (i < 5)
return i + 1.0;
else if (i % 2 == 0)
return i / 2.0;
else
return i * i;
}
ЗахватпеременныхизвнешнегоконтекстаExample123_Lambda3[] // без захвата переменных из внешней области видимости
[=] // все переменные захватываются по значению
[&] // все переменные захватываются по ссылке
[this] // захват текущего класса
[x, y] // захват x и y по значению
[&x, &y] // захват x и y по ссылке
[in, &out] // захват in по значению, а out — по ссылке
[=, &out1, &out2] // захват всех переменных по значению, кроме out1 и out2,
// которые захватываются по ссылке
[&, x, &y] // захват всех переменных по ссылке, кроме x…
Взболтатьнонесмешивать: lambda+std::asyncExample124_LambdaAsync
1.// создаем vector для результатов вычислений2. std::vector<std::future < double>> results;
3.// запускаем подзадачи с помощью std::async4. for (int i = 0; i < 100; i++)5. results.push_back(std::async([i]() -> double {6. double result = 0;7. for(int j=1;j<=STEP;j++) result+= std::log10(i*STEP+j);8. return result;9. }));
10.// собираем результаты11. for (auto &i : results) val+=i.get();
Генерациялямбда-выраженийExample125_LambdaGenerationНачинаясостандартаC++11шаблонныйклассstd::function являетсяполиморфнойоберткойфункцийдляобщегоиспользования.Объектыклассаstd::function могутхранить,копироватьивызыватьпроизвольныевызываемыеобъекты- функции,лямбда-выражения,выражениясвязыванияидругиефункциональныйобъекты.Говорявобщем,влюбомместе,гденеобходимоиспользоватьуказательнафункциюдляеёотложенноговызова,илидлясозданияфункцииобратноговызова,вместонегоможетбытьиспользованstd::function,которыйпредоставляетпользователюбольшуюгибкостьвреализации.
Определениекласса
template<class> class function; // undefined
template<class R, class... ArgTypes> classfunction<R(ArgTypes...)>;
Чтоещепочитать?C++ConcurrencyinActionPracticalMultithreadingAnthonyWilliams
February,2012|528pagesISBN:9781933988771
Разныеблоги,например:
http://habrahabr.ru/post/182610/
top related