Създаване и изчакване на нишки

Създаване и изчакване на поток

Нека да видим прост пример

В този пример вътре в основната нишка, в която се изпълнява основната функция, се създава нова нишка, вътре в която се извиква функцията helloWorld. Функцията helloWorld показва поздрав. Поздрав се показва и в основната нишка. След това потоците се комбинират.

Създава се нова нишка с помощта на функцията pthread_create

Функцията получава като аргументи указател към нишка, променлива от типа pthread_t, в която, ако е успешна, записва идентификатора на нишката. pthread_attr_t - атрибути на нишки. Ако се използват атрибутите по подразбиране, тогава може да се предаде NULL. start_routin е директно функцията, която ще бъде изпълнена в новата нишка. arg са аргументите, които ще бъдат предадени на функцията.

Нишката може да прави много различни неща и да получава различни аргументи. За да направи това, функцията, която ще се изпълнява в нова нишка, приема аргумент от тип void *. Поради това можете да обгърнете всички предадени аргументи в структура. Можете също така да върнете стойност чрез предадения аргумент.

При успех функцията връща 0. Ако са възникнали грешки, могат да се върнат следните стойности

  • ИЗВЪН - системата няма ресурси за създаване на нова нишка или системата вече не може да създава нишки, тъй като броят на нишките е надвишил стойността на PTHREAD_THREADS_MAX (например на една от машините, които се използват за тестване, тази магия номер е 2019)
  • EINVAL - невалидни атрибути на потока (предадени от аргумента attr)
  • EPERM - Извикващата нишка няма подходящите права за задаване на необходимите параметри или правила за планиране.

Нека да преминем през програмата

Тук задаваме набора от стойности, необходими за обработка на възможни грешки.

Това е функция, която ще работи в отделна нишка. Тя няма да получи никакви аргументи. Според стандарта се счита, че изричен изход от функцията извиква функцията pthread_exit и връщаната стойност ще бъде предадена при извикване на функцията pthread_join като статус.

Тук се създава и веднага се изпълнява нова нишка. Потокът не получава никакви атрибути или аргументи. След създаване на поток се извършва проверка за грешка.

Причинява основната нишка да изчака завършването на хайвера. Функция

Забавя изпълнението на извикващата нишка (тази функция), докато нишката бъде изпълнена. Когато pthread_join е успешен, той връща 0. Ако нишката изрично е върнала стойност (това е същата стойност УСПЕХ от нашата функция), тогава тя ще бъде поставена в променливата value_ptr. Възможни грешки, върнати от pthread_join

  • EINVAL - нишката сочи към несменяема нишка
  • ESRCH - няма нишка със същия идентификатор, съхранявана в променливата на нишката
  • EDEADLK - бе открито блокиране (блокиране) или самата извикваща нишка беше посочена като нишка, която се обединява.

Пример за създаване на потоци с предаване на аргументи към тях

Е, ние искаме да предадем данни на потока и да върнем нещо обратно. Например ще предадем низ в потока и ще върнем дължината на този низ от потока.

Тъй като функция може да получи само указател void, всички аргументи трябва да бъдат пакетирани в структура. Нека дефинираме нова структура тип:

Тук id е идентификаторът на потока (обикновено не е необходим в нашия пример), второто поле е низ, а третото е дължината на низа, който ще върнем.

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

В случай, че всичко е минало добре, тогава връщаме стойността SUCCESS като състояние и ако е допусната грешка (в нашия случай, ако е предаден нулев низ), тогава излизаме със състоянието BAD_MESSAGE.

В този пример ще създадем 4 нишки. За 4 нишки ви е необходим масив от тип pthread_t с дължина 4, масив от предадени аргументи и 4 реда, които ще предадем.

На първо място, попълваме стойностите на аргументите.

След това създаваме нови нишки в цикъла

След това чакаме завършване

Накрая показваме и аргументите, които сега съхраняват върнатите стойности. Имайте предвид, че един от аргументите е "лош" (низът е NULL). Ето пълния код

Направете го няколко пъти. Имайте предвид, че редът на изпълнение на нишките не е детерминиран. Като стартирате програмата, можете да получите различен ред на изпълнение всеки път.