Использование pthreads для двух функций в C - PullRequest
1 голос
/ 22 ноября 2010

Я совершенно новичок в pthreads и, похоже, на всех сайтах, на которые я смотрел, много ненужной информации.

У меня есть две функции, давайте пока просто назовем их X и Y, обе они работают с блоками в памяти.Если в одном потоке выполняется XI, я не хочу, чтобы другие потоки вызывали X или Y в том же блоке, как я могу убедиться, что этого никогда не произойдет?

Нужно ли блокировать мьютекс функции для определенных значений блока?

Ответы [ 4 ]

2 голосов
/ 22 ноября 2010

Вам нужно будет использовать мьютексы.

Вы не должны блокировать код, вы должны блокировать данные.Создайте мьютекс для каждого блока и заблокируйте его, пока функция работает с блоком, а затем разблокируйте его, когда закончите.

Мьютекс - это тип, определенный в pthread.h, pthread_mutex_t.Предоставляются функции для блокировки и разблокировки мьютекса.Эти функции гарантируют, что только один поток может получить блокировку за раз (если вы просто использовали переменную, чтобы указать, что ваш блок используется, у вас будут проблемы параллелизма с этой переменной вместо блока).

В Интернете доступно множество учебников.Google "pthread tutorial", и вы должны найти достаточно, чтобы начать.

1 голос
/ 22 ноября 2010

Вы блокируете ресурс - в данном случае блок памяти - мьютексом. В качестве альтернативы вы можете заблокировать только те части кода функций, которые читают / обновляют эту область памяти. Это называется критическим разделом и требует другого подхода к кодированию. Это означает, что ваши потоки могут свободно работать, кроме случаев, когда они попадают в ту часть, где они взаимодействуют с ресурсом.

Первый метод проще реализовать - просто подход «все или ничего» для всей функции X или Y.

0 голосов
/ 23 ноября 2010

Многопоточное программирование действительно лучше разрешается при использовании языков более высокого уровня.Некоторые вещи сложно понять в C, и, на мой взгляд, многопоточность является одной из них.Я обнаружил, что Java дала мне лучшее представление о проблемах и проблемах.В нем легче понять концепции и легче читать документацию.Инфраструктура C ++, такая как Poco или Qt, также была бы лучше, если бы Java не была для вас идеей.

Как уже говорили другие, концептуально вы хотите заблокировать ресурсы (в вашем случае это часть памяти).Семафоры, как концепция, подходят к этой проблеме гораздо лучше, чем мьютекс.Я бы исследовал семафоры и просто думал о мьютексах как о строительном блоке семафоров.Если вы спросите меня, мьютекс - это плохо названный двоичный семафор.

0 голосов
/ 23 ноября 2010

Возможно, какой-то демонстрационный код в порядке. Предположим, у вас есть заголовок блока, например:

struct block {
    void *data;
    size_t len;
};

Вы бы защитили блок, добавив переменную мьютекса в эту структуру:

struct block {
    void *data;
    size_t len;
    pthread_mutex_t lock;
};

Затем необходимо обновить функцию инициализации для этой структуры, чтобы инициализировать блокировку:

struct block *new_block(size_t len)
{
    struct block *b = malloc(sizeof *b);
    b->data = malloc(len);
    b->len = len;

    pthread_mutex_init(&b->lock, NULL);

    return b;
}

Функции X и Y (и любая другая функция, которая читает или записывает в блок) затем должны взять блокировку и отпустить ее при выходе:

int x(struct block *b)
{
    int retval;

    pthread_mutex_lock(&b->lock);

    /* code */

    pthread_mutex_unlock(&b->lock);
    return retval;
}

int y(struct block *b)
{
    int retval;

    pthread_mutex_lock(&b->lock);

    /* code */

    pthread_mutex_unlock(&b->lock);
    return retval;
}

Вы должны быть осторожны, чтобы гарантировать, что вы разблокируете мьютекс даже в пути возврата ошибки.

...