Squeak.ru - шаблоны программирования

Мьютекс навсегда блокирует значение в функции

Я новичок в темах в c. В моем коде есть поток, который увеличивает счетчик, и иногда (случайно) другой поток считывает этот счетчик. Я использовал мьютекс в этом коде, но мой код всегда дает мне значение, равное 1. Хотя я использовал pthread_mutex_unlock, но кажется, что значение становится заблокированным навсегда. что я должен сделать, чтобы решить проблему?

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <pthread.h>
///////////////////////////

long int count=0;
int RunFlag=0;
pthread_mutex_t mtx;

void *readfun(void *arg)
{
    while (RunFlag==0)
    {
        pthread_mutex_lock(&mtx);
        count=count+1;
        pthread_mutex_unlock(&mtx);
    }

}
void *printfun(void *arg)
{
    int RadnTime=0;
    for (int j=0;j<4;j++)
    {
        RadnTime=rand()%3+1;
        sleep(RadnTime);

        printf("The current counter after %d seconds is: ",RadnTime);
        pthread_mutex_lock(&mtx);
        printf("%d\n",count);
        pthread_mutex_unlock(&mtx);
    }



}

void main ()
{
    pthread_t thread1;
    pthread_t thread2;

    pthread_mutex_init(&mtx, NULL);

    pthread_create(&thread1,NULL,readfun,NULL);
    pthread_create(&thread2,NULL,printfun,NULL);

    //stop the counter
    RunFlag=1;

    pthread_exit(NULL);
}

Ответы:


1

Вы устанавливаете RunFlag сразу после создания двух потоков, поэтому readfun едва успевает выполняться. RunFlag=1; должно быть в конце printfun.


Насколько я знаю, чтение и запись в RunFlag не гарантируется атомарностью, поэтому доступ к нему также должен быть защищен. Я не вижу здесь проблемы (учитывая рассматриваемые значения), но вы входите на территорию неопределенного поведения.


Ваши функции ничего не возвращают, даже если они объявлены как возвращающие void*. Добавьте к ним return NULL;.


Наконец, второй %d должен быть %ld, так как count — это long int.


Обратите внимание, что

pthread_mutex_t mtx;
pthread_mutex_init(&mtx, NULL);

можно заменить на

pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
13.12.2016
  • Это оставит гонку данных. 13.12.2016
  • Конечно, есть. RunFlag записывается в одном потоке, а читается в другом без защиты. 13.12.2016
  • Это неопределенное поведение. Указано здесь: 5.1.2.4 §25 13.12.2016
  • Проблема с RunFlag не имеет значения, потому что нам все равно, пройдет ли поток чтения дальше RunFlag == 0 после установки флага. Если он добавляется к count после того, как ему сказали остановиться, это не имеет большого значения. 13.12.2016
  • Было три неполных ответа и ни одного полного ответа, поэтому я впитал недостающие фрагменты в свой. 13.12.2016
  • Звонки @ikegami pthread_join() вообще не нужны. В файле main есть pthread_exit(). Инициализация мьютекса в порядке, поскольку она выполняется с использованием pthread_mutex_init(). 13.12.2016
  • @usr, я скопировал часть PTHREAD_MUTEX_INITIALIZER из твоего ответа! /// Вы уверены, что вызов pthread_exit(NULL); в основном потоке будет ждать завершения других потоков? Это не ясно из документов. 13.12.2016
  • @ikegami Не проблема обратиться к вещам, отмеченным в комментариях и ответах других, но, похоже, таким образом вы составили весь ответ. Хотя это законно по правилам SO, мне было бы неловко делать это без особого собственного вклада. Во всяком случае, это мое личное мнение (у вас все в порядке). Чтобы в основном потоке дождаться завершения других потоков? Это не ясно из документов: он не будет ждать других потоков, просто другие потоки будут продолжать выполняться, и, следовательно, нет необходимости присоединяться. 13.12.2016
  • @usr. Вы шутите, Из 4-х задач, обозначенных ответом, только одна пришла из чужого ответа. (Был второй, который оказался неправильным). Как я уже говорил, один полный ответ лучше, чем три неполных. 13.12.2016
  • @usr, ну и какой именно? Вы сказали, что процесс не будет ждать их завершения и что потоки будут продолжать работать. Это взаимоисключающие. 13.12.2016
  • Вы сказали, что процесс не будет ждать, пока они закончатся, я никогда этого не говорил. Я предлагаю вам прочитать документацию POSIX, если вы не понимаете. 13.12.2016
  • @usr, да, твои точные слова были он не будет ждать других тем. /// Кажется, я читал документы POSIX. Если вы имеете в виду нечто иное, чем этого, укажите это! 13.12.2016

  • 2

    1) У вас также есть гонка данных, так как двое обращаются к RunFlag. Итак, вам нужно защитить его с помощью примитива синхронизации (например, мьютекса или использования семафора).

    Но вам не нужен RunFlag для этой цели. Так как вы можете использовать бесконечный цикл в потоке readfun(), а затем просто вызвать _exit() из потока printfun(), чтобы выйти из всего процесса.

    2) Функции потоков должны возвращать указатель, чтобы удовлетворять требованиям pthread_create(). требование. Но ваши потоковые функции ничего не возвращают. Вы можете добавить return NULL; в конце обеих функций потока.

    Помните о переполнении целого числа со знаком, так как count потенциально может переполниться.

    13.12.2016
    Новые материалы

    Угловая структура архитектуры
    Обратите внимание, что эта статья устарела, я решил создать новую с лучшей структурой и с учетом автономных компонентов: https://medium.com/@marekpanti/angular-standalone-architecture-b645edd0d54a..

    «Данные, которые большинство людей используют для обучения своих моделей искусственного интеллекта, поставляются со встроенным…
    Первоначально опубликовано HalkTalks: https://hacktown.com.br/blog/blog/os-dados-que-a-maioria-das-pessoas-usa-para-treinar-seus-modelos-de-inteligencia-artificial- ja-vem-com-um-vies-embutido/..

    Сильный ИИ против слабого ИИ: различия парадигм искусственного интеллекта
    В последние годы изучению и развитию искусственного интеллекта (ИИ) уделяется большое внимание и прогресс. Сильный ИИ и Слабый ИИ — две основные парадигмы в области искусственного интеллекта...

    Правильный способ добавить Firebase в ваш проект React с помощью React Hooks
    React + Firebase - это мощная комбинация для быстрого и безопасного создания приложений, от проверки концепции до массового производства. Раньше (знаете, несколько месяцев назад) добавление..

    Создайте API с помощью Python FastAPI
    Создание API с помощью Python становится очень простым при использовании пакета FastAPI. После установки и импорта вы можете создать приложение FastAPI и указать несколько конечных точек. Каждой..

    Веселье с прокси-сервером JavaScript
    Прокси-серверы JavaScript — это чистый сахар, если вы хотите создать некоторую общую логику в своих приложениях, чтобы облегчить себе жизнь. Вот один пример: Связь клиент-сервер Мы..

    Получить бесплатный хостинг для разработчиков | Разместите свой сайт за несколько шагов 🔥
    Статические веб-сайты — это веб-страницы с фиксированным содержанием и его постоянным содержанием. Но теперь статические сайты также обрабатывают динамические данные с помощью API и запросов...


    © 2024 squeak.ru, Squeak.ru - шаблоны программирования