sleep方法将程序线程挂在C pthread中

问题描述 投票:0回答:1

我用pthreads创建了一个C程序,它可以完美工作,直到添加任何形式的sleep函数,无论它是sleep()还是usleep()或nanosleep()。

是的,在您问之前,我知道usleep()已被弃用,并且我已从另一stackoferflow帖子中复制了nanosleep()的正确用法,但即使sleep()也不起作用。

代码(关键部分位于“客户”线程中的第99行):

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdlib.h>
#include <time.h>

#define LIBERA 0
#define OCCUPATA 1
#define TUTTE_SEDIE_OCCUPATE -1
#define OCCUPATA_DA_BARBIERE -2

#define NRCLIENTI 10
#define NRSEDIE 5

pthread_mutex_t poltrona_m, dorme_m, get_sedia_m, occupa_sedia_m;
sem_t sem;
int sedia_taglio = LIBERA, sedia_attesa[NRSEDIE];

void init_attr(void) {
    int i;
    for (i = 0; i < NRSEDIE; i++)
        sedia_attesa[i] = LIBERA;
    sem_init(&sem, 0, NRSEDIE);
    pthread_mutex_unlock(&poltrona_m);
    pthread_mutex_unlock(&dorme_m);
    pthread_mutex_unlock(&get_sedia_m);
    pthread_mutex_unlock(&occupa_sedia_m);
}

int my_sleep(long millis) {
    struct timespec req, rem;

    if (millis > 999) {
        req.tv_sec = (int) (millis / 1000);
        req.tv_nsec = (millis - ((long) req.tv_sec * 1000)) * 1000000;
    } else {
        req.tv_sec = 0;
        req.tv_nsec = millis * 1000000;
    }

    return nanosleep(&req, &rem);
}

int get_sedia_libera() {
    pthread_mutex_lock(&get_sedia_m);
    int i;
    for (i = 0; i < NRSEDIE; i++)
        if (sedia_attesa[i] == LIBERA)
            return i;
    pthread_mutex_unlock(&get_sedia_m);
    return TUTTE_SEDIE_OCCUPATE;
}

int occupa_sedia(int index) {
    pthread_mutex_lock(&occupa_sedia_m);
    int result;
    if(sedia_attesa[index] == LIBERA){
        sedia_attesa[index] = OCCUPATA;
        result = 1;
    }else
        result = 0;
    pthread_mutex_unlock(&occupa_sedia_m);
    return result;
}

void libera_sedia(int index) {
    sedia_attesa[index] = LIBERA;
}

void *barbiere(void *arg) {
    while (1)
    {
        if (sedia_taglio == OCCUPATA) {
            pthread_mutex_lock(&poltrona_m);
            sedia_taglio = LIBERA;
            pthread_mutex_unlock(&poltrona_m);
        }

        if (get_sedia_libera() == 0 && sedia_taglio == LIBERA) {
            sedia_taglio = OCCUPATA_DA_BARBIERE;
            pthread_mutex_lock(&dorme_m);
            printf("[BARBIERE] il barbiere dorme...\n");
        }
    }
}

void *cliente(void *arg) {
    int n;
    int *id = (void *)arg;

    while (1)
    {
        if (sedia_taglio == LIBERA || sedia_taglio == OCCUPATA_DA_BARBIERE) {

            pthread_mutex_lock(&poltrona_m);
            pthread_mutex_unlock(&dorme_m);
            sedia_taglio = OCCUPATA;
            printf("----[CLIENTE] Cliente \"%d\" si taglia i capelli!\n", *id);
            my_sleep(2000);
            sedia_taglio = LIBERA;
            pthread_mutex_unlock(&poltrona_m);
            pthread_exit(0);

        } else {
            n = get_sedia_libera();
            if(n == TUTTE_SEDIE_OCCUPATE) {
                fprintf(stderr, "----[CLIENTE] No posti liberi cliente \"%d\" lascia il negozio\n", *id);
                pthread_exit((void *)1);
            } else {
                sem_wait(&sem);
                n = get_sedia_libera();
                if(occupa_sedia(n) && n != TUTTE_SEDIE_OCCUPATE){
                    printf("----[CLIENTE] Cliente \"%d\" aspetta su sedia #%d\n", *id, n+1);
                    while (sedia_taglio != LIBERA);
                    sem_post(&sem);
                    libera_sedia(n);
                } else {
                    sem_post(&sem);
                    fprintf(stderr, "----[CLIENTE] No posti liberi cliente \"%d\" lascia il negozio\n", *id);
                    pthread_exit(0);
                }
            }
        }

    }
}

int main(int argc, char **argv) {

    init_attr();

    int i, id[NRCLIENTI];
    pthread_t barbiere_thread, cliente_thread[NRCLIENTI];

    if(pthread_create(&barbiere_thread, NULL, barbiere, NULL ) < 0){
        fprintf(stderr, "[MAIN] Error creating \"barber\" thread!\n");
        exit(EXIT_FAILURE);
    }
    printf("[MAIN] thread \"barber\" creato\n\n");

    for (i = 0; i < NRCLIENTI; ++i) {
        id[i] = i+1;
        printf("[MAIN] thread \"client %d\" creato\n", id[i]);
        if(pthread_create(&cliente_thread[i], NULL, cliente, &id[i]) < 0){
            fprintf(stderr, "[MAIN] Error creating \"client %d\" thread!\n", id[i]);
            exit(EXIT_FAILURE);
        }
    }

    for (i = 0; i < NRCLIENTI; i++){
        pthread_join(cliente_thread[i], NULL);
        printf("[MAIN]Joined client \"%d\"\n", i+1);
    }

    //il programma non finira mai se sta ad aspettare un thread con un ciclo while(1) al suo interno
    //senza condizioni di break!!!
    pthread_join(barbiere_thread, NULL);

    return 0;
}

正常执行(这是程序应该的工作方式:] >>

[MAIN] thread "client 1" creato
[BARBIERE] il barbiere dorme...
hey
[MAIN] thread "client 2" creato
----<<<<<<<<<<<<[CLIENTE] Cliente "1" si taglia i capelli!
[MAIN] thread "client 3" creato
----<<<<<<<<<<<<[CLIENTE] Cliente "2" si taglia i capelli!
[MAIN] thread "client 4" creato
----<<<<<<<<<<<<[CLIENTE] Cliente "3" si taglia i capelli!
[MAIN] thread "client 5" creato
----<<<<<<<<<<<<[CLIENTE] Cliente "4" si taglia i capelli!
[MAIN] thread "client 6" creato
----<<<<<<<<<<<<[CLIENTE] Cliente "5" si taglia i capelli!
[MAIN] thread "client 7" creato
----<<<<<<<<<<<<[CLIENTE] Cliente "6" si taglia i capelli!
[MAIN] thread "client 8" creato
----<<<<<<<<<<<<[CLIENTE] Cliente "7" si taglia i capelli!
[MAIN] thread "client 9" creato
----<<<<<<<<<<<<[CLIENTE] Cliente "8" si taglia i capelli!
[MAIN] thread "client 10" creato
----<<<<<<<<<<<<[CLIENTE] Cliente "9" si taglia i capelli!
----<<<<<<<<<<<<[CLIENTE] Cliente "10" si taglia i capelli!
[MAIN]Joined client "1"
[MAIN]Joined client "2"
[MAIN]Joined client "3"
[MAIN]Joined client "4"
[MAIN]Joined client "5"
[MAIN]Joined client "6"
[MAIN]Joined client "7"
[MAIN]Joined client "8"
[MAIN]Joined client "9"
[MAIN]Joined client "10"

执行任何睡眠方法,sleep(1),具有1秒或100k微秒usleep()的nanosleep()

但是我不考虑usleep()因为 a)*不推荐使用,* b)您不能放置超过或等于100万微秒; usleep(1000000)无效
[MAIN] thread "client 1" creato
[BARBIERE] il barbiere dorme...
[MAIN] thread "client 2" creato
----[CLIENTE] Cliente "1" si taglia i capelli!
[MAIN] thread "client 3" creato
[MAIN] thread "client 4" creato
[MAIN] thread "client 5" creato
[MAIN] thread "client 6" creato
[MAIN] thread "client 7" creato
[MAIN] thread "client 8" creato
[MAIN] thread "client 9" creato
[MAIN] thread "client 10" creato
[MAIN]Joined client "1"

如您所见,线程只是...停顿。我等了终端打开了5分钟,但仍然没有任何变化。

最奇怪的是,如果我使用MinGW在Windows IntelliJ Clion中运行此命令,则sleep()函数似乎被完全忽略了(程序在不到一秒钟的时间内执行完毕)!

感谢您通读所有这些内容,希望我们能找到解决方案,对于获得的任何帮助,我将不胜感激!

我创建了一个带有pthreads的C程序,它可以完美工作,直到添加任何形式的sleep函数,无论它是sleep()还是usleep()或nanosleep()。是的,在您问之前,我知道usleep()是...

c pthreads
1个回答
0
投票

使用几个嵌套的mutexes

© www.soinside.com 2019 - 2024. All rights reserved.