Synchronizace - obrácený semafor

Synchronizace - obrácený semafor
« kdy: 29. 10. 2017, 18:49:18 »
Ve svém kódu jsem začal používat objekt, který funguje obráceně než semafor. Je to counter, který mohu zvyšovat a snižovat a případně mohu nařídit jinému vláknu, aby bylo zastaveno, dokud se na counteru neobjeví nula.

Typicky to používám tak, že chci aby thread počkal, dokud se nedokončí všechny paralelní operace, přičemž stačí počítat, kolik jich ještě běží. Pokud všechny skončí, klesne čítač na nulu a thread může pokračovat.

A teď hledám na google, jak se toto synchronizační primitivum jmenuje. Protože klasický semafor to není, bariera taky ne. Google mi nepomůže, protože se ho neumím zeptat. Pomůže mi někdo?


gll

Re:Synchronizace - obrácený semafor
« Odpověď #1 kdy: 29. 10. 2017, 19:05:28 »
atomic_int ?



Re:Synchronizace - obrácený semafor
« Odpověď #2 kdy: 29. 10. 2017, 19:10:17 »
Třída, která umí jen snižovat, se v Javě jmenuje CountDownLatch. Obecně pak funguje Phaser. Zda to má i nějaké obecné názvy nevím.

v

Re:Synchronizace - obrácený semafor
« Odpověď #3 kdy: 29. 10. 2017, 19:21:03 »

gll

Re:Synchronizace - obrácený semafor
« Odpověď #4 kdy: 29. 10. 2017, 19:28:07 »
Typicky to používám tak, že chci aby thread počkal, dokud se nedokončí všechny paralelní operace, přičemž stačí počítat, kolik jich ještě běží. Pokud všechny skončí, klesne čítač na nulu a thread může pokračovat.

Pro tuhle konkrétní situaci by šlo možná použít nějakou obdobu thread_group z boostu. Nemusel byste se starat o inkrementaci a dekrementaci čítače.


lopata

Re:Synchronizace - obrácený semafor
« Odpověď #5 kdy: 29. 10. 2017, 20:09:14 »

Re:Synchronizace - obrácený semafor
« Odpověď #6 kdy: 29. 10. 2017, 20:09:33 »
Typicky to používám tak, že chci aby thread počkal, dokud se nedokončí všechny paralelní operace, přičemž stačí počítat, kolik jich ještě běží. Pokud všechny skončí, klesne čítač na nulu a thread může pokračovat.

Pro tuhle konkrétní situaci by šlo možná použít nějakou obdobu thread_group z boostu. Nemusel byste se starat o inkrementaci a dekrementaci čítače.

No já to nepoužívám jen na vlákna, ale obecně na počítání úloh. Těch může být víc jak vláken, přičemž některé se vykonávají, jiné jsou ve frontě. Cílem je zastavit nějaké vlákno, dokud nejsou úlohy hotové.

Re:Synchronizace - obrácený semafor
« Odpověď #7 kdy: 29. 10. 2017, 20:12:03 »
Condition variable.
https://en.m.wikipedia.org/wiki/Monitor_(synchronization)

Ano, používám na to condition_variable, chtěl jsem to vyčlenit z projektu a strčit do nějaké společné knihovny a dát tomu rozumný název. Zatím se to jmenuje MTCounter

Kód: [Vybrat]
class MTCounter {
public:

void inc() {
std::unique_lock<std::mutex> _(lock);
counter++;
}
void dec() {
std::unique_lock<std::mutex> _(lock);
if (counter) {
counter--;
if (counter == 0) {
waiter.notify_all();
}
}
}
bool zeroWait(unsigned int timeout_ms) {
std::unique_lock<std::mutex> _(lock);
return waiter.wait_for(_,std::chrono::milliseconds(timeout_ms), [=]{return counter == 0;});
}
void zeroWait() {
std::unique_lock<std::mutex> _(lock);
waiter.wait(_,[=]{return counter == 0;});
}

unsigned int getCounter() const {
return counter;
}

void setCounter(unsigned int counter) {
std::unique_lock<std::mutex> _(lock);
this->counter = counter;
if (counter == 0) {
waiter.notify_all();
}
}

protected:
std::mutex lock;
std::condition_variable waiter;
unsigned int counter = 0;
};

lopata

Re:Synchronizace - obrácený semafor
« Odpověď #8 kdy: 30. 10. 2017, 01:48:36 »
V metodě getCounter není korektní takhle přistupovat k proměnné counter bez mutexu. Mutex musí být pro zápis i čtení, jinak je tam race condition.

.

Re:Synchronizace - obrácený semafor
« Odpověď #9 kdy: 30. 10. 2017, 11:03:08 »
V metodě getCounter není korektní takhle přistupovat k proměnné counter bez mutexu. Mutex musí být pro zápis i čtení, jinak je tam race condition.
Já bych to ještě doplnil, že samotná funkce getCounter je velice sporná, pokud by měla sloužit k čemukoliv jinému než nějaké statistice.

Re:Synchronizace - obrácený semafor
« Odpověď #10 kdy: 30. 10. 2017, 16:16:49 »
V metodě getCounter není korektní takhle přistupovat k proměnné counter bez mutexu. Mutex musí být pro zápis i čtení, jinak je tam race condition.
Já bych to ještě doplnil, že samotná funkce getCounter je velice sporná, pokud by měla sloužit k čemukoliv jinému než nějaké statistice.

Ta funkce má smysl, pokud ji používá jediné vlákno, které zároveň s counterem manipuluje. Tam pak mutex není potřeba, protože jen to jedno vlákno ho čte a mění. Zároveň v situaci, kdy těch vláken mám víc, pak ta funkce smysl nemá a volat ji taky smysl nemá. Proto je tam mutex v zásadě zbytečný.

atarist

Re:Synchronizace - obrácený semafor
« Odpověď #11 kdy: 30. 10. 2017, 17:32:23 »
jsou v C++ ve vychozim stavu thread safe?

atarist

Re:Synchronizace - obrácený semafor
« Odpověď #12 kdy: 30. 10. 2017, 18:10:23 »
jsou v C++ ve vychozim stavu thread safe?

chybí mi tam "jsou atributy objektů"... (sorry, nejde editovat ani vlastní příspěvek)

Re:Synchronizace - obrácený semafor
« Odpověď #13 kdy: 30. 10. 2017, 18:21:00 »
jsou v C++ ve vychozim stavu thread safe?

Jestli C++ jsou atributy thread safe? Odpověď zní NE. A ani to není žádoucí protože zajištění thread safety je výkonově drahé a obecně se snažíme jakékoliv interakce mezi thready minimalizovat aby se to muselo řešit na co nejméně mistech.

V tomto konkrétním případě jde o to že atribut counter není thread safe ale taky jeho čtení v okamžiku používání vícero vlákny je samo sebou nesmyslné protože může vracet stará data a teoreticky může dojít k poškození údaje při čtení a zároveň zápisu jiným vláknem. (Prakticky se to ale při čtení intu nestane). Nicméně se nepředpokládá nějaké praktické využití v tomto režimu je to spíš kvůli možnosti výpisu vnitřního stavu pro účely nějakého ladění a logovánI

PJ

Re:Synchronizace - obrácený semafor
« Odpověď #14 kdy: 30. 10. 2017, 19:33:31 »
Vola sa to Barrier alebo WaitGroup.

Skoro urcite to riesis zle. Na cakanie na dokoncenie operacie (alebo operacii) je lepsi promise/future. S nimi nemusis riesit take tie problemy ako "pripocital som?", "nie je tam race condition?" a podobne. Ked sa ti podari deadlock, tak byva deterministicky. Caka to prave na hodnoty, ktore chces pouzit.