使用多线程解决读写慢问题

问题描述

业务上用到对于产品带宽批量请求的情况,而读写接口是单线程的,并且是每次读写都有超时等待2秒,这就造成如果出现批量请求就需要等待很长时间。

解决思路

把数据的发送和接收分开,数据接收单独放到一个线程里。
之前是一次读一个值,改为一次多个值,这样就节省了读取次数和时间。

代码示例

初始化
主线程

write()
...
read()
...

创建子线程

if( (ret=pthread_create( &(m_tid), NULL, __udp_recvproc, NULL )) != 0 ) 

子线程
__udp_recvproc 是线程处理函数,用于处理数据的接收。
而在线程处理函数中,针对不同类型的请求,可以使用不同的逻辑进行处理。

数据修改处理

使用线程锁对数据进行读写保护。
用到的几个函数:

pthread_mutex_init( &m_tunnel_mutex, NULL );
pthread_mutex_lock( &m_tunnel_mutex );
pthread_mutex_unlock( &m_tunnel_mutex );
pthread_mutex_destroy( &m_tunnel_mutex );

使用信号量实现对数据的读写超时处理

当读写数据需要返回结果时,需要一个等待时间,如果单纯用sleep函数对系统资源消耗过大,我们采用信号量的函数进行,既实现超时等待,又能保证速度,即等到数据就立即返回,而不是每次都死板的等待一定间隔。

使用举例

  • 信号量初始化
sem_init( &(m_sem), 0, 0 );

第一个参数:信号量名
看一个例子,比如有两个线程都要往打印机上打东西,但是同一时刻只能打一个。那么首先用sem_init初始化一个信号量,注意pshared表示允许几个进程共享该信号量,一般设0用于进程内的多线程共享,要看是否支持进程共享,请查看下你的系统的man手册。

第三个参数value表示可用的资源的数目,即信号灯的数目,咱们这儿只有1个打印机所以设成1。然后线程调用sem_wait取获取这个信号灯,第一个线程一看,有1个,他就拿到了,然后可以继续后继操作,此时信号灯自动减1,变成0个。那么第二个线程调用sem_wait时就会阻塞在这儿了。第一个线程完成打印后,调用sem_post释放信号灯,信号灯数目变成1,将会唤醒等待的第二个线程,然后第二个线程接着打印。最后当所有任务完成后,主线程调用sem_destroy释放这个信号量。

  • 等待数据是设置等待超时信号量
struct timespec abs_timeout;
clock_gettime( CLOCK_REALTIME, &abs_timeout);
abs_timeout.tv_sec += 1;
abs_timeout.tv_nsec=0;
if( sem_timedwait( &m_readsem, &abs_timeout ) == 0 )
{
	pthread_mutex_unlock( &m_tunnel_mutex );
	return 1;
}

这里sem_timedwait的作用是,等待一个abs_timeout时间,再次时间内等待信号时,就把信号减1,并且立即返回。如果超时了也返回,这就达到了不会一直等待的目的。

  • 接收数据处理
sem_post( &m_readsem );

这里是接收数据处理时,接收到数据后,信号量+1,这样上面的等待数据就等到结果,然后立即返回了。

  • 信号量资源释放
sem_destroy( &(m_sem) );

—全文完–

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值