0

gcc (GCC) 4.6.3 c89 valgrind-3.6.1

こんにちは、

更新されたコード スニペット +++++++++++++++++++++++++++++++++++

void *thread_recv_fd()
{
    pthread_mutex_lock(&mutex_queue);
    while(start_receiving) {
        pthread_mutex_unlock(&mutex_queue);

        pthread_mutex_lock(&mutex_queue);
        queue_remove();
        pthread_mutex_unlock(&mutex_queue);

        usleep(500);
    }

    pthread_exit(NULL);
}

上記のロックを使用すると、非常に見苦しくなります。そして、..の読み取りでまだ競合エラーが発生しますstart_receiving。また、揮発性としても宣言しました。+++++++++++++++++++++++++++++++++++++++

1/2 秒ごとにポーリングするワーカー スレッドで while ループを実行しています。ユーザーがctrl-cを入力すると、値がfalseに変更されるグローバル変数start_recomingで制御します。

このようなグローバルを持つことは良い習慣ですか?

helgrind を実行するとこれら 2 つのエラーが発生するので、私が尋ねた理由は次のとおりです。

==6814== Possible data race during write of size 4 at 0x601958 by thread #1
==6814==    at 0x401131: main (driver.c:78) 
==6814==  This conflicts with a previous read of size 4 by thread #2
==6814==    at 0x4012A7: thread_recv_fd (driver.c:127)

これはコード行です:

driver.c:78 is this line of code start_receiving = FALSE;
driver.c:127 is this line of code while(start_receiving) in the while loop

ソースコード、重要なスニペットのみ:

static int start_receiving = FALSE;

int main(void)
{
    pthread_t thread_recv_id;
    pthread_attr_t thread_attr;

    /* Start polling as soon as thread has been created */
    start_receiving = TRUE;

    do {
        /* Start thread that will send a message */
        if(pthread_create(&thread_recv_id, &thread_attr, thread_recv_fd, NULL) == -1) {
            fprintf(stderr, "Failed to create thread, reason [ %s ]",
                    strerror(errno));
            break;
        }
    }
    while(0);

    /* Wait for ctrl-c */
    pause(); 

    /* Stop polling - exit while loop */
    start_receiving = FALSE;

    /* Clean up threading properties */
    pthread_join(thread_recv_id, NULL);

    pthread_exit(NULL);
}

void *thread_recv_fd()
{
    while(start_receiving) {
        pthread_mutex_lock(&mutex_queue);
        queue_remove();
        pthread_mutex_unlock(&mutex_queue);

        usleep(500);
    }

    pthread_exit(NULL);
}

ご提案いただきありがとうございます。

4

3 に答える 3

3

いいえ、それは非常に悪い習慣です。

少なくとも、変数はvolatile最適化されないようにする必要があります。

ただし、ミューテックス (共有状態を保護し、2 つのスレッドが同時にアクセスしないようにするため) やアトミック変数 (状態を確認するため) など、実際のマルチスレッド プリミティブを使用することを検討する必要があります。スレッドプルーフです)。

于 2012-04-10T14:58:40.823 に答える
1

投票は正しい方法ではありません。条件変数について読むことをお勧めします

于 2012-04-10T15:20:46.850 に答える
1

アトミックを使用することもできますが、ここでの最も簡単な解決策は、制御変数をロックすることです。例えば:

static int start_receiving = FALSE;
static pthread_mutex_t start_receiving_lock = PTHREAD_MUTEX_INITIALIZER;

int is_receiving(void)
{
    int r;

    pthread_mutex_lock(&start_receiving_lock);
    r = start_receiving;
    pthread_mutex_unlock(&start_receiving_lock);

    return r;
}

次に、スレッド関数で:

void *thread_recv_fd()
{
    while(is_receiving()) {
        pthread_mutex_lock(&mutex_queue);
        queue_remove();
        pthread_mutex_unlock(&mutex_queue);

        usleep(500);
    }

    pthread_exit(NULL);
}

..そしてメイン関数で:

pthread_mutex_lock(&start_receiving_lock);
start_receiving = 1;
pthread_mutex_unlock(&start_receiving_lock);
于 2012-04-11T06:42:38.713 に答える