c - pthread 互斥体中的意外行为

标签 c multithreading mutex

好吧,我已经定义了 2 个互斥体:bar_mutex(在 N 个 bar 线程之间使用)和 writer_mutex(在 bar 线程和观察者线程中使用)。编写器互斥体用于避免变量 k_total 的奇怪值,我正在修改一个全局变量,但在某些特定时刻该变量变为 0.0,而另一个线程将其与该值一起使用。 为了避免这种情况,我添加了 writer_mutex 但问题仍然存在。我究竟做错了什么?我将粘贴代码的重要部分。

if (k_total < 1 && b->cm <=20) {
    b->cm = b->cm + 10; //Usando este valor calculamos el deltak
    /* printf("\nThread yendo hacia abajo\n"); */
    if (b->direction == UP) {
        b->direction = DOWN;
        changed_direction = true;
    } else {
        changed_direction = false;
    }
} else if(k_total > 1 && b->cm >=-20) {
    b->cm = b->cm - 10; //Usando este valor calculamos el deltak
    /* printf("\nThread yendo hacia arriba\n"); */
    if (b->direction == DOWN) {
        b->direction = UP;
        changed_direction = true;
    } else {
        changed_direction = false;
    }
}

In this part of the function move_bar k_total is taken as 0 instead of the correct value... In order to avoid this I added the writer_mutex but it is still not working

enter image description here

Here you can see the global variable ktotal is being sent as 0 in some point... I am trying to avoid this.

我将附加代码的主要部分。

void
start_threads(struct bar* bars) {
    int i;
    pthread_t threads[NUM_THREADS + 1];
    bars = (struct bar*)malloc(sizeof(struct bar) * NUM_THREADS);
    init_variables();
    pthread_mutex_init(&bar_mutex, NULL);
    pthread_mutex_init(&write_mutex, NULL);
    pthread_cond_init(&unstable_state, NULL);

    for (i = 1; i < NUM_THREADS + 1; i++) {
        fill_bar(&bars[i - 1], i);
    }

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    // creating the 4 threads that handle each bar
    for (i = 0; i < NUM_THREADS; i++) {
        pthread_create(&threads[i], &attr, move_bar, (void *)&bars[i]);
    }
    //thread used to check if system is stable and change its k_total
    pthread_create(&threads[NUM_THREADS], &attr, check_stable, (void*)bars);

    /* Wait for all threads to complete */
    for (i=0; i<NUM_THREADS + 1; i++) {
        pthread_join(threads[i], NULL);
    }
}

void*
check_stable(void* bars) {
    struct bar* wires = (struct bar*) bars ;
    while (true) {
        pthread_mutex_lock(&write_mutex);
        k_total = 0.0;
        for (int i = 0; i < NUM_THREADS; ++i) {
            k_total += getDeltaKValue(wires[i].cm);
        }

        char str[25];
        sprintf(str,"deltak=%lf", k_total);
        doPost("deltak",str);

        k_total = k_value + k_total;

        sprintf(str,"kparcial=%lf",k_value);
        doPost("kparcial",str);
        sprintf(str,"ktotal=%lf", k_total);
        doPost("ktotal",str);
        if ((double)k_total != (double)1.0) {
            unbalanced = true;
            pthread_cond_signal(&unstable_state);
        } else {
            unbalanced = false;
        }
        pthread_mutex_unlock(&write_mutex);
        sleep(1);
    }
}

void*
move_bar(void *bar) {
    struct bar* b = (struct bar*) bar;
    clock_t start = clock();
    bool changed_direction = false;
    while (true) {
        pthread_mutex_lock(&bar_mutex);
        while (unbalanced == false)
            pthread_cond_wait(&unstable_state, &bar_mutex);
        pthread_mutex_lock(&write_mutex);
        if (k_total < 1 && b->cm <=20) {
            b->cm = b->cm + 10; //Usando este valor calculamos el deltak
            /* printf("\nThread yendo hacia abajo\n"); */
            if(b->direction == UP) {
                b->direction = DOWN;
                changed_direction = true;
            } else {
                changed_direction = false;
            }
        } else if (k_total > 1 && b->cm >=-20) {
            b->cm = b->cm - 10; //Usando este valor calculamos el deltak
            /* printf("\nThread yendo hacia arriba\n"); */
            if(b->direction == DOWN) {
                b->direction = UP;
                changed_direction = true;
            } else {
                changed_direction = false;
            }
        }

        k_total = 0.0;
        for (int i = 0; i < NUM_THREADS; ++i) {
            k_total += getDeltaKValue(bars[i].cm);
        }
        char str[25];
        if ((double)k_total != (double)1.0) {
            unbalanced = true;
        } else {
            printf("\nBALANCED");
            unbalanced = false;
        }

        pthread_mutex_unlock(&write_mutex);

        if (changed_direction) {
            sleep(CHANGE_DIRECTION);
        }
        sleep(MOVEMENT_TIME);

        sprintf(str,"id=%ld&cm=%d",b->id, b->cm);
        doPost("barValue",str);

        /* printf("\nEnding thread %ld", b->id); */
        changed_direction = false;
        pthread_mutex_unlock(&bar_mutex);
        sleep(1); 
    }
    pthread_exit(NULL);
}

最佳答案

好吧,伙计们,问题不在这里。该代码确实有效。使用 gdb,我看到有 2 个全局变量 bars 具有相同的名称,但具有不同的引用,因为我正在为同一个变量执行 2 个 malloc,并且我一直在更新机器人的 2 个不同函数中使用该变量结构而不只是 1...我刚刚删除了意外的 malloc,一切正常。

关于c - pthread 互斥体中的意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45857257/

相关文章:

c++ - C++ 中的锁和互斥锁

c - 为什么这些构造使用增量前和增量后未定义的行为?

java - 如何告诉 Runnable 抛出 InterruptedException?

java - Java-服务器可同时为多个客户端提供服务

java - 何时创建新的 ForkJoinPool 以及何时使用 CommonPool?

rust - 如何像在 Go 中锁定结构一样锁定 Rust 结构?

c - 在 C 中使用线程编程时的棘手死锁

c - fprintf 导致控制台应用程序崩溃

c - C中的**指针和*指针

c++ - 使用已编译版本的 openCV 时出错