Используем потоки в Linux C++

Каждый разработчик рано или поздно сталкивается с необходимостью создания потока. Ведь нельзя решить практически ни одну сложную задачу выполняя только одну задачу за раз.
В Linux имеется собственная реализация потоков. Для создания потока существует функция pthread_create:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, 
    void *(*start_routine)(void*), void *arg);
  • pthread_t *thread — указатель на поток
  • const pthread_attr_t *attr — атрибуты потока (если NULL — стандартные)
  • void *(*start_routine)(void*) — имя функции выполняемой в потоке
  • void *arg — параметр передаваемый функции.

Возвращает данная функция 0 если всё успешно и номер ошибки если нет.
После создания потока можно приступать к ожиданию его завершения — pthread_join:

int pthread_join(pthread_t thread, void **value_ptr);

Первый параметр — указатель на поток, второй — практически всегда NULL.
Кроме того поток можно завершить досрочно:

pthread_cancel(thread);

Теперь давайте создадим небольшую программу для наглядности.
Создадим приложение с двумя потоками.
Библиотеки:

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#include <iostream>
using namespace std;

Определим функцию для потока:

void * thread_func(void *arg){
    int i;
    int loc_id = * (int *) arg;
    for (i = 0; i < 4; i++) {
        printf("Поток %i работает\n", loc_id);
        sleep(1);
    }
}

В функции main зададим основные переменные:

int main(int argc, char * argv[]){
    int id1, id2, result;
    pthread_t thread1, thread2;

Зададим идентификатор потока. Не путайте с системным идентификатором! Это всего лишь переменная для нашей программы!

    id1 = 1;

Создадим потока и проверим ошибки:

    result = pthread_create(&thread1, NULL, thread_func, &id1);
    if (result != 0) {
        perror("Создание первого потока!");
        return EXIT_FAILURE;
    }

Тоже повторим для второго потока:

    id2 = 2;
    result = pthread_create(&thread2, NULL, thread_func, &id2);
    if (result != 0) {
        perror("Создание второго потока");
        return EXIT_FAILURE;
    }

Отделим момент для наглядности примера:

    sleep(2);
    cout << "Ждём конца!\n";

Ждём завершения первого и второго потока:

    result = pthread_join(thread1, NULL);
    if (result != 0) {
        perror("Ждём первый поток");
        return EXIT_FAILURE;
    }
    result = pthread_join(thread2, NULL);
    if (result != 0) {
        perror("Ждём второй поток");
        return EXIT_FAILURE;
    }

Выводим сообщение о конце и выходим из программы:

    printf("Done\n");
    return EXIT_SUCCESS;
}

Вывод программы такой:

Поток 1 работает
Поток 2 работает
Поток 1 работает
Поток 2 работает
Ждём конца!
Поток 1 работает
Поток 2 работает
Поток 1 работает
Поток 2 работает
Done

Обратите ваше внимание на то, что чтобы откомпилировать программу придётся задать флаг -D_REENTERANT и библиотеки:

g++ threads.cpp -D_REENTERANT -I/usr/include/nptl -L/usr/lib/nptl –lpthread -o threads

Хотя я создавал проект в Qt Creator и qmake разобрался сам 😉

 

Похожий код:

Фото аватара
Алексей Петров

Программист, разработчик с 5 летним опытом работы. Учусь на разработчика игр на Unity и разработчика VR&AR реальности (виртуальной реальности). Основные языки программирования: C#, C++.

Оцените автора
Бла, бла код
Добавить комментарий

  1. Максим

    Огромное спасибо, все доступно и понятно!)

    Ответить