linux c++ 线程支持 多核应用,linux C++多线程服务端开发

linux C++多线程服务端开发

UNIX

线程安全的对象生命期管理

当析构函数遇到多线程

构造不要在构造函数中注册任何回调

不要在构造函数中把this传给跨线程的对象

即便在构造函数的最后一行也不行,因为这个类可能是基类,构造完基类还要构造派生类,就是怕对象未构造完成,却暴露且使用了this

销毁太难如果线程A对x对象要执行析构,线程B对x要调用update函数,会出问题。

如果用mutex,也不行,比如A获得了互斥锁,进而进行了析构,B虽然阻塞在锁上在等待A释放,但是A已经析构了,B是继续阻塞?天晓得接下来发生什么。

delete之后,把相关变量置为NULL,也是没用的。

作为数据成员的mutex不能保护析构mutexLock可以保证读写正确,但是无法保证析构正确

只有别的线程都访问不到这个对象的时候,析构才安全

如果要同时读这个类的两个对象,有可能发生死锁,比如两个线程分别执行swap(a,b),swap(b,a);

线程安全的Observer有多难一个动态创建的对象是否还或者,光看指针是看不出来的,引用也一样。如果已经销毁就不可能根据里面的状态判断,更不能根据这个指针的值(万一又创建了呢,这种方法是C指针问题的根源)。

简单的方法是只创建不销毁,不够就开辟,用完就放回去。这样至少可疑避免访问失效对象的情况。但是这种山寨方法的问题有:

全局共享数据引发的lockcontention。

对象池的线程安全,如何完全,安全把对象放回去现在要解决的问题是用的时候一定知道对象还活着

要想安全销毁对象,最好在别人(线程)都看不到的情况下,偷偷地做,垃圾回收的原理就是这个

空悬指针

jj

线程同步

线程同步四项原则,按照重要性排列:最低限度共享对象,较少需要同步的场合。

使用高级的并发编程构件

最后使用底层同步原语。使用互斥器和条件变量,慎用读写锁,不要用信号量。

互斥器用RAII手法封装mutex的创建,销毁,加锁,解锁。

只用非递归的mutex

不手工调用lock,unlock,一切交给构造和析构函数

不适用跨进程的mutex,只用tcp sockets

加锁,解锁在同一线程

条件变量

解决互斥锁阻塞的问题

intdequeue(){

lock(mutex);

while(queue.empty())

{

cond.wait();

}

inttop=queue.front();

queue.pop_front();

returntop;

}

voidenqueue(intx){

lock(mutex);

queue.push_back(x);

cond.notify();

}

读写锁

效率不比mutex快。

信号量

条件变量和互斥锁的结合可以替代其功能,而且不易用错。

多线程服务器的适用场合与编程模型多线程可以共享数据,而且更好的利用多核。

单核服务器利用多线程每多少价值

多线程常见模型每个请求创建一个线程,使用阻塞是I/O。

适用线程池,同样使用阻塞IO,与第一种相比,提高了性能。

适用non-blocking IO + IO multiplexing 即,Java NIO

leader/follower 等高级模式

默认情况下是第三种。

one loop per thread

推荐使用one loop per thread + thread pool

进程间通信的方式很多,pipe,FIFO,共享内存,消息队列,还有一些同步原语。

推荐使用TCP,因为如果多进程依然无法满足服务,就需要扩充到其他机器,易于扩展

如果用很少的cpu负载就能让IO跑满,或者用很少的IO流量就可疑让cpu跑满,那么多线程没啥用处。静态web服务器,FTP服务器,cpu的负载很小,主要瓶颈在磁盘IO和网络IO,这时候一个单线程的程序就可疑撑满IO。多线程并不能提高吞吐量。

cpu跑满很少见,比如m个数,找出n个数,使其和为0.,能把cpu算死。这种情况,多启动几个单线程的进程就可疑了。

适合多线程的场景

虽然多线程不能提高绝对性能,但能提高平均响应性能。多核

有数据共享,如果没有数据共享,则用多个进程解决

数据可以修改,如果数据都是敞亮表,就可以在进程间用shared memory,多个进程(每个进程一个线程)

提供非均质的服务,即,时间的相应有优先级差别,可以用专门的线程处理优先级高的

一个好的多线程程序,应该可以享受cpu数目增加带来的好处

32位的机器,4G的地址空间,用户态可以访问3G,如果不修改栈的调用空间10M,300个线程

疑难解答多线程能提高并发度吗?如果指的是并发连接数,则不能。如果单纯采用thread per connection的模型,并发连接数是300,这个远远低于基于事件的单线程程序能轻松到达的并发连接数(几千乃至上完)。基于事件,指的是用IO multiplexing event loop 的编程模型,Reactor。一个multi-loop的多线程程序应该能轻松支持5W。thread不适合高并发的场合。

多线程能提高吞吐量吗?,对于计算密集型服务,不能。

多线程可以降低响应时间吗?可以。如果设计合理,充分利用多核资源的话,可以。

多线程的进程和多个单线程的进程如何取舍。可以根据工作集的大小来取舍。

如果程序有一个较大的cache,几乎每次请求都会访问,多线程会适合,因为这样可以避免每个进程保存一份cache

多线程日志

对于C++程序,最好整个程序使用相同的日志库,程序有一个正体的日志输出,而不要各个组件有各个组件的日志输出。一般的日志风格有两种借助printf();,log_info("");

借助stream<

日志的功能需求

因为日志库不能每条消息都flush到硬盘,也不能每条日志都open/close文件(开销太大)。方法定期(默认3秒)将缓冲区的日志消息flush到硬盘

每条日志消息都带有一个cookie(或者叫哨兵值/sentry),其值是某个函数地址,这样通过coredump文件可疑找到cookie,这样就可以找到尚未写到磁盘的消息。

日志消息格式要点:每条日志占一行。

时间戳精确到微妙。

打印线程id,便于分析多线程的时序,也可以检测死锁。

日志级别。

文件的名字行号。

日志的性能需求

日志库要足够高效。输出足够多的诊断信息,减小运维难度,提升效率。每秒几千上万条日志没有明显的性能损失。

能应对一个进程产生大量日志的场景,比如1GB/min

不阻塞正常的执行流程

在多线程程序中,不造成争用。

性能指标磁盘带宽约110MB/s,日志库应该能瞬间写满这个带宽。

假如每条是110字节,意味着每秒要写100万条

多线程异步日志

用多个buffer,缓冲

muduo网络库简介

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值