C语言中的线程信号控制详解

 更新时间:2023年02月03日 09:02:42   作者:我要出家当道士  
这篇文章主要通过一些示例为大家详细介绍一下C语言中的线程信号控制,文中的示例代码讲解详细,对我们深入了解C语言有一定的帮助,感兴趣的可以学习一下

一、场景介绍

存在三个线程,一个主线程和两个子线程(子线程数量不固定)。为了节省频繁创建销毁线程造成的资源浪费,将这些线程设置为常驻线程。但这样引入了一个新的问题,如何协调这些线程完成工作。

主线程内是循环检测某个文件夹内文件的变动,当文件夹内出现新的文件时,更新可拷贝文件列表,并告知子线程开始干活;子线程拷贝结束后需要告知主线程任务完成了,主线程开始下一轮检测。

二、解决方法

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 的空转,当信号可操作时也会立即执行,不会增加操作时延。

到此这篇关于C语言中的线程信号控制详解的文章就介绍到这了,更多相关C语言线程信号控制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言数据结构与算法之队列的实现详解

    C语言数据结构与算法之队列的实现详解

    队列只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)的原则。本文将通过实例详细说说队列的实现,需要的可以学习一下
    2022-10-10
  • C语言实现数独游戏的求解

    C语言实现数独游戏的求解

    这篇文章主要为大家详细介绍了C语言实现数独游戏的求解,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01
  • C/C++中命名空间(namespace)详解及其作用介绍

    C/C++中命名空间(namespace)详解及其作用介绍

    今天小编就为大家分享一篇关于C++命名空间namespace的介绍与使用,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2021-09-09
  • 老生常谈C语言中指针的使用

    老生常谈C语言中指针的使用

    这篇文章主要为大家详细介绍了C语言中指针的使用,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • VS2019使用Windows桌面应用程序模块创建Win32窗口

    VS2019使用Windows桌面应用程序模块创建Win32窗口

    这篇文章主要介绍了VS2019使用Windows桌面应用程序模块创建Win32窗口,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04
  • C++ vector的常见用法超详细讲解

    C++ vector的常见用法超详细讲解

    这篇文章主要介绍了C++ vector的常见用法,包括C++中vector容器的定义、初始化方法、访问元素、常用函数及其时间复杂度,通过代码介绍的非常详细,需要的朋友可以参考下
    2025-04-04
  • C++模板编程特性之移动语义

    C++模板编程特性之移动语义

    首先,移动语义和完美转发这两个概念是在C++的模板编程的基础上,新增的特性,主要是配合模板来使用。本篇会从C++的值类型,到移动拷贝与移动赋值来理解移动语义与完美转发
    2022-08-08
  • C++string容器基本概念详解

    C++string容器基本概念详解

    c++相比c的一个好处就是实现了很多的容器和泛型算法,使得程序员的工作得到了很大的简化,本文重点给大家介绍C++string容器基本概念讲解,需要的朋友参考下吧
    2021-07-07
  • C/C++浮点数使用的两个注意事项详解

    C/C++浮点数使用的两个注意事项详解

    浮点数都是有符号的,没有 unsigned 浮点数,下面这篇文章主要给大家介绍了关于C/C++浮点数使用的两个注意事项,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • VC++角色游戏中的人物初始化模块代码实例

    VC++角色游戏中的人物初始化模块代码实例

    这篇文章主要介绍了VC++角色游戏中的人物初始化模块,对大家学习VC++有一定的帮助,需要的朋友可以参考下
    2014-08-08

最新评论