簡體   English   中英

在 Linux 中使用 pthreads 執行打印的順序

[英]Order of execution of print with pthreads in Linux

我正在使用 C 並且我想通過多線程在 output 屏幕中獲取字符串“ABCABCABCABCABCABC”。 一個線程顯示“A”字符,第二個線程顯示“B”,第三個線程顯示“C”。 如果我編譯以下代碼:

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

#define cantidad_impresion_letra 6
pthread_mutex_t semaforo = PTHREAD_MUTEX_INITIALIZER;

void *escribirA(void *unused){
    int i;
    for(i=0;i<cantidad_impresion_letra;i++){
        pthread_mutex_lock(&semaforo);
        printf("A");
        pthread_mutex_unlock(&semaforo);
    }
}

void *escribirB(void *unused){
    int i;
    for(i=0;i<cantidad_impresion_letra;i++){
        pthread_mutex_lock(&semaforo);
        printf("B");
        pthread_mutex_unlock(&semaforo);
    }
}

void *escribirC(void *unused){
    int i;
    for(i=0;i<cantidad_impresion_letra;i++){
        pthread_mutex_lock(&semaforo);
        printf("C");
        pthread_mutex_unlock(&semaforo);
    }
}

int main(){
    pthread_t thread1, thread2, thread3;
    
    pthread_create(&thread1,NULL,escribirA,NULL);
    pthread_create(&thread2,NULL,escribirB,NULL);
    pthread_create(&thread3,NULL,escribirC,NULL);
        
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    pthread_join(thread3, NULL);
    
    return(0);
}

在 Windows 通過 Dev-C++ 上,控制台拋出我: ABACBACBACBACBACBC但如果我在 Linux 中編譯相同的代碼,我得到CCCCCCBBBBBBAAAAAA
有人可以解釋一下嗎?

您可以將執行順序存儲在名為order的全局 volatile 變量中,該變量循環設置為值 0、1 和 2(由於增量和模運算)。 使用條件變量檢查此變量:

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

volatile int order = 0;

#define cantidad_impresion_letra 6
pthread_mutex_t semaforo = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;


void *escribirA(void *unused){
    int i;
    for(i=0;i<cantidad_impresion_letra;i++){
        pthread_mutex_lock(&semaforo);
        while (order != 0) {
          // Wake up another thread before going to sleep
          pthread_cond_signal(&cond);
          pthread_cond_wait(&cond, &semaforo);
        }
        printf("A");
        order = (order + 1) % 3;
        fflush(stdout);
        // Wake up another thread
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&semaforo);
    }
}

void *escribirB(void *unused){
    int i;
    for(i=0;i<cantidad_impresion_letra;i++){
        pthread_mutex_lock(&semaforo);
        while (order != 1) {
          // Wake up another thread before going to sleep
          pthread_cond_signal(&cond);
          pthread_cond_wait(&cond, &semaforo);
        }
        printf("B");
        order = (order + 1) % 3;
        fflush(stdout);
        // Wake up another thread
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&semaforo);
    }
}

void *escribirC(void *unused){
    int i;
    for(i=0;i<cantidad_impresion_letra;i++){
        pthread_mutex_lock(&semaforo);
        while (order != 2) {
          // Wake up another thread before going to sleep
          pthread_cond_signal(&cond);
          pthread_cond_wait(&cond, &semaforo);
        }
        printf("C");
        order = (order + 1) % 3;
        fflush(stdout);
        // Wake up another thread
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&semaforo);
    }
}

int main(){
    pthread_t thread1, thread2, thread3;
    
    pthread_create(&thread1,NULL,escribirA,NULL);
    pthread_create(&thread2,NULL,escribirB,NULL);
    pthread_create(&thread3,NULL,escribirC,NULL);
        
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    pthread_join(thread3, NULL);
    
    return(0);
}

執行示例:

$ gcc order.c -o order -lpthread
$ ./order
ABCABCABCABCABCABC

在 Windows 通過 Dev-C++,控制台拋出我:ABACBACBACBACBACBC 但如果我在 Linux 中編譯相同的代碼,我得到 CCCCCCBBBBBBAAAAAA。 有人可以解釋一下嗎?

Linux 行為是您應該期待的。 某些線程必須首先開始運行。 無論是哪個線程,其他兩個線程都會被阻塞。 該線程將能夠繼續運行一段時間,因為它不需要等待。

您在 Windows 中看到的行為很糟糕——可能是最糟糕的。 要么保持所有三個線程都安排好,要么沒有。 如果它讓所有三個線程都安排好,那么它使用三個核心來完成僅用一個核心就可以同樣快速地完成的工作。 如果它沒有讓所有三個線程都安排好,那么您將在 output 的每個字符中獲得一個上下文切換,並且因為您剛剛從另一個任務切換而浪費 CPU 時間不斷填充代碼和數據緩存。

有人可以解釋一下嗎?

linux 中不同的 output 與使用的調度程序有關。

人計划

自 Linux 2.6.23 起,默認調度程序是 CFS,即“完全公平調度程序”。

完全公平的調度程序

每個 cfs_rq 類型的 per-CPU run-queue 以時間順序將sched_entity 結構排序為紅黑樹(或 Linux 術語中的“rbtree”),其中最左邊的節點被接收到最少切片的實體占用執行時間(保存在實體的 vruntime 字段中)。 節點由處理器“執行時間”索引,以納秒為單位。

這意味着什么:

每個線程運行得如此之快,以至於調度程序認為沒有必要執行上下文切換。

只有 6 個迭代步驟和一個 output 到一個緩沖的 stream (沒有換行,因此沒有 output 到終端,直到發生刷新)。

做測試,增加迭代步驟,向 output 添加更多字符並添加換行符( \n )。

順序將開始改變。

在我的系統上,序列開始隨着 200 個迭代步驟和 3 個字符(加上\n )發生變化。


我正在使用 C 並且我想獲取字符串“ABCABCABCABCABCABC”

順序 output 最好通過順序執行來實現。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM