Условно изчакване

Когато използвате boost::conditional_variable, ACE_Conditional или директно pthread_cond_wait, има ли допълнителни разходи за самото изчакване? Това са по-специфични проблеми, които създават проблеми:

  1. След като чакащата нишка е непланирана, ще бъде ли планирана обратно преди изтичането на изчакването и след това отново непланирана или ще остане непланирана, докато не бъде сигнализирана?
  2. wait придобива ли периодично мютекса? В този случай предполагам, че всяка итерация губи малко процесорно време при системни извиквания за заключване и освобождаване на мютекса. Същото ли е като непрекъснато придобиване и пускане на мютекс?
  3. Освен това колко време минава между сигнала и връщането от wait?

Afaik, когато се използват семафори, отзивчивостта на повикванията за придобиване зависи от размера на времевия отрязък на планировчика. Как работи в pthread_cond_wait? Предполагам, че това зависи от платформата. Интересувам се повече от Linux, но ако някой знае как работи на други платформи, също ще помогне.

И още един въпрос: има ли допълнителни системни ресурси, разпределени за всяко условие? Няма да създам 30 000 мютекса в кода си, но трябва ли да се тревожа за 30 000 условни израза, които използват един и същ мютекс?


person FireAphis    schedule 18.10.2010    source източник


Отговори (2)


Ето какво пише в man страницата на pthread_cond:

pthread_cond_wait атомарно отключва мутекса и изчаква променливата на условието cond да бъде сигнализирана. Изпълнението на нишката е спряно и не изразходва време на процесора, докато не бъде сигнализирана променливата за условие.

Така че от тук нататък бих отговорил на въпросите, както следва:

  1. Чакащата нишка няма да бъде планирана обратно, преди чакането да бъде сигнализирано или отменено.
  2. Няма периодични придобивания на mutex. Мутексът се придобива повторно само веднъж, преди да се върне изчакването.
  3. Времето, което минава между сигнала и връщането на изчакване, е подобно на това при планирането на нишка поради освобождаване на mutex.

По отношение на ресурсите, на същата страница с ръководство:

В реализацията на LinuxThreads никакви ресурси не са свързани с променливи на условие, така че pthread_cond_destroy всъщност не прави нищо, освен да проверява дали условието няма чакащи нишки.

Актуализация: Разрових се в източниците на функциите pthread_cond_* и поведението е следното:

  1. Всички условни pthread в Linux се изпълняват чрез futex.
  2. Когато нишка извика wait, тя е спряна и не е планирана. Идентификаторът на нишката се вмъква в края на списък с чакащи нишки.
  3. Когато нишка извика signal, нишката в началото на списъка се планира обратно. Така че събуждането е толкова ефективно, колкото и планировчикът, не се изразходват ресурси на ОС и единственото натоварване на паметта е размерът на списъка с чакащи (вижте futex_wake функция).
person FireAphis    schedule 19.10.2010

Трябва да извикате pthread_cond_wait само ако променливата вече е в "грешно" състояние. Тъй като винаги чака, винаги има режийни разходи, свързани с поставянето на текущата нишка в режим на заспиване и превключването.

Когато нишката е непланирана, тя е непланирана. Не трябва да използва никакви ресурси, но разбира се една ОС на теория може да бъде внедрена зле. Разрешено е повторно придобиване на мютекса и дори връщане преди сигнала (поради което трябва да проверите отново условието), но операционната система ще бъде внедрена, така че това няма да повлияе много на производителността, ако се случи в всичко. Това не се случва спонтанно, а по-скоро в отговор на друг, вероятно несвързан сигнал.

30 000 мутекса не би трябвало да са проблем, но някои операционни системи може да имат проблем с 30 000 спящи нишки.

person Potatoswatter    schedule 18.10.2010
comment
Благодаря за отговора. Имам нужда от пояснение - след като чакащата нишка е непланирана, ще бъде ли планирана обратно преди изтичането на чакането и след това отново непланирана или ще остане непланирана до сигнализиране? - person FireAphis; 19.10.2010
comment
@Fire: Не съм сигурен какво имаш предвид под изтича. От вас се изисква да извикате функцията като while ( ! condition() ) pthread_cond_wait(…);, където condition е каквото и да е булево значение true, за да продължи изпълнението, така че ако cond_wait се върне преждевременно, просто я извикайте отново. Но както казах, много операционни системи никога не правят това и дори да го правят, обикновено не е проблем. Ако имате таймаут, формата е while ( ! condition() && pthread_cond_timedwait(…) != ETIMEDOUT ) ;. - person Potatoswatter; 19.10.2010