網(wǎng)站首頁 編程語言 正文
一、場景介紹
存在三個線程,一個主線程和兩個子線程(子線程數(shù)量不固定)。為了節(jié)省頻繁創(chuàng)建銷毀線程造成的資源浪費,將這些線程設置為常駐線程。但這樣引入了一個新的問題,如何協(xié)調(diào)這些線程完成工作。
主線程內(nèi)是循環(huán)檢測某個文件夾內(nèi)文件的變動,當文件夾內(nèi)出現(xiàn)新的文件時,更新可拷貝文件列表,并告知子線程開始干活;子線程拷貝結(jié)束后需要告知主線程任務完成了,主線程開始下一輪檢測。
二、解決方法
1、臨時線程
主線程每次檢測完畢后,新建子線程執(zhí)行拷貝任務,并阻塞等待線程任務的結(jié)束。
#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)優(yōu)點
邏輯簡單
(2)缺點
頻繁創(chuàng)建與銷毀線程,資源浪費。
2、全局變量信號
定義一個全局變量作為線程的控制信號。
主線程將該信號設置為子線程的個數(shù)的負數(shù),以啟動子線程。
當該信號小于 0 時,子線程開始啟動。子線程的啟動與任務完畢都需要將該信號加一。
當主線程檢測到該信號為線程總數(shù)時推導子線程本次任務結(jié)束。
(1)優(yōu)點
子線程作為常駐線程,節(jié)省了一定的資源。
(2)缺點
子線程與主線程在等待信號的過程中要么造成 CPU 的空轉(zhuǎn),要么 sleep 會增加程序的處理時延。
而且,子線程啟動與結(jié)束都對全局信號進行加一的操作,極端情況(某些線程執(zhí)行速度存在極端差異)下可能造成信號控制的紊亂。
3、信號量
使用兩組信號:start_signal 和 over_signal。
主線程啟動子線程時,需要將 start_signal 賦值為子線程數(shù),over_signal 賦值為0.
子線程執(zhí)行down(start_signal) ,該操作執(zhí)行成功即可執(zhí)行任務邏輯,執(zhí)行完后 up(over_signal)。
主線程需要執(zhí)行 num 次down(over_signal)操作,只有所有子線程執(zhí)行結(jié)束,該操作才可以執(zhí)行完成。
在等待執(zhí)行信號down和up的過程中,線程都是阻塞的,不會造成 CPU 的空轉(zhuǎn),當信號可操作時也會立即執(zhí)行,不會增加操作時延。
原文鏈接:https://blog.csdn.net/qq_37437983/article/details/128822183
相關推薦
- 2022-09-12 詳解APScheduler如何設置任務不并發(fā)_python
- 2022-06-09 基于Python實現(xiàn)對比Exce的工具_python
- 2022-06-25 Python制作簡易計算器功能_python
- 2022-07-21 element 中l(wèi)oading顏色的修改
- 2022-05-09 C#特性(Attribute)_C#教程
- 2022-02-24 C語言數(shù)據(jù)結(jié)構(gòu)與算法之排序總結(jié)(一)_C 語言
- 2022-06-13 Python數(shù)據(jù)類型及常用方法_python
- 2022-10-28 C++異步操作future和aysnc與function和bind_C 語言
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支