日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C語言中的線程信號控制詳解_C 語言

作者:我要出家當道士 ? 更新時間: 2023-04-02 編程語言

一、場景介紹

存在三個線程,一個主線程和兩個子線程(子線程數量不固定)。為了節省頻繁創建銷毀線程造成的資源浪費,將這些線程設置為常駐線程。但這樣引入了一個新的問題,如何協調這些線程完成工作。

主線程內是循環檢測某個文件夾內文件的變動,當文件夾內出現新的文件時,更新可拷貝文件列表,并告知子線程開始干活;子線程拷貝結束后需要告知主線程任務完成了,主線程開始下一輪檢測。

二、解決方法

1、臨時線程

主線程每次檢測完畢后,新建子線程執行拷貝任務,并阻塞等待線程任務的結束。

#include "main.h"
 
void *filecopy_thread(void *args)
{
    pthread_t id = pthread_self();
    PTHREAD_ARGS *thread_args = (PTHREAD_ARGS *)args;
    string dst_dir = thread_args->dst_dir;
    while (1)
    {
        // get the file to copy
        pthread_mutex_lock(thread_args->mutex);
        // exit when the list is empty
        if (thread_args->file_list.empty())
        {
            pthread_mutex_unlock(thread_args->mutex);
            break;
        }
        string src_file = thread_args->file_list.back();
        thread_args->file_list.pop_back();
        pthread_mutex_unlock(thread_args->mutex);
        copy_file(src_file, dst_dir);
    }
    return NULL;
}
 
 
int main(int argc, char **argv)
{
    while(1)
    {
        bool is_switch = oracle.is_redolog_switch();
 
        // judge whether the redolog has bean switched
        if ( is_switch )
        {
            printf("pthread create\n");
            pthread_t *pthread_list = (pthread_t *)malloc(sizeof(pthread_t) * cfg_utils.m_filecopy_pcount);
            if (!pthread_list)
            {
                LOG_F(ERROR, "pthread list created failed");
                continue;
            }
            pthread_mutex_t mutex;
            pthread_mutex_init(&mutex, NULL);
            PTHREAD_ARGS pthread_args = {file_list_src, &mutex, cfg_utils.m_logbk_syspath, &oncebk_count};
            
            struct timeval start, end;
            gettimeofday(&start, NULL);
                        
            // start file copy thread
            for (int i = 0; i < cfg_utils.m_filecopy_pcount; i++)
            {
                 printf("creating pthread(%d)\n", i + 1);
                pthread_create(pthread_list + i, NULL, filecopy_thread, &pthread_args);
            }
            // block until all file has copied
            for (int i = 0; i < cfg_utils.m_filecopy_pcount; i++)
            {
                pthread_join(pthread_list[i], NULL);
            }
            
            gettimeofday(&end, NULL);
            double timeuse = ( end.tv_sec - start.tv_sec ) + (end.tv_usec - start.tv_usec)/1000000.0;
            printf("%.1lf(s)\n", timeuse);
            
            pthread_mutex_destroy(&mutex);
            free(pthread_list);
 
        }
        sleep(cfg_utils.m_bk_cycle);
    }
    return 0;
}

(1)優點

邏輯簡單

(2)缺點

頻繁創建與銷毀線程,資源浪費。

2、全局變量信號

定義一個全局變量作為線程的控制信號。

主線程將該信號設置為子線程的個數的負數,以啟動子線程。

當該信號小于 0 時,子線程開始啟動。子線程的啟動與任務完畢都需要將該信號加一。

當主線程檢測到該信號為線程總數時推導子線程本次任務結束。

(1)優點

子線程作為常駐線程,節省了一定的資源。

(2)缺點

子線程與主線程在等待信號的過程中要么造成 CPU 的空轉,要么 sleep 會增加程序的處理時延。

而且,子線程啟動與結束都對全局信號進行加一的操作,極端情況(某些線程執行速度存在極端差異)下可能造成信號控制的紊亂。

3、信號量

使用兩組信號:start_signal 和 over_signal。

主線程啟動子線程時,需要將 start_signal 賦值為子線程數,over_signal 賦值為0.

子線程執行down(start_signal) ,該操作執行成功即可執行任務邏輯,執行完后 up(over_signal)。

主線程需要執行 num 次down(over_signal)操作,只有所有子線程執行結束,該操作才可以執行完成。

在等待執行信號down和up的過程中,線程都是阻塞的,不會造成 CPU 的空轉,當信號可操作時也會立即執行,不會增加操作時延。

原文鏈接:https://blog.csdn.net/qq_37437983/article/details/128822183

欄目分類
最近更新