《C++游戏服务器开发入门到掌握》多线程编程

本文介绍了C++11在游戏服务器多线程编程中的应用,涵盖死锁、乱序、并发访问数据等问题,以及新概念如高阶接口、低阶接口。通过实例展示了线程的创建、资源共享、原子操作、mutex的使用,讨论了线程间的交互和同步方法,旨在帮助读者掌握C++游戏服务器开发中的多线程技术。
摘要由CSDN通过智能技术生成

63、游戏服务器的基础

单核也可多线程,只不过要切换线程有额外开销,所以随着现在多核的出现,更适合多线程发展。目前CPU有4核、8核、16核,运行内存有8G、16G、32G。

可能的问题
  1. 死锁;
  2. 乱序;
  3. 并发访问数据;
  4. 低效率(为了防止前面问题的发生,需要做很多防御性工作)。
C++11带来的新概念
  1. 高阶接口:(async, future);
  2. 低阶接口:(thread, mutex);
例子:
void helloworld() {
   
	std::cout << "hello world\n";
}
int main() {
   
	// 一个进程本身有一个线程
	std::thread t(helloworld); // 开启一个线程
	std::cout << "hello main thread\n";
	t.join(); // 等待此线程运行结束(线程的终结)
}

64、例子:计算量一分二

  • 描述: 一千万次非常耗时的计算,可以折半分给额外的线程。注意要先创建线程去执行,再执行主线程的。否则按代码顺序执行,额外线程不仅没有利用起来,还增加了额外开销。
  • 再次使用lambda: 创建线程时传入的是std::function,传统的函数名(C类型的函数指针)会自动转换为function,如果需要传入参数,或接受返回值,可以用lambda实现(Lua中有用过,所以还能理解)。std::thread s([&value, iterBeg, iterEnd]() { value = func(iterBeg, iterEnd; }); // func为实际要执行的函数
函数内部如何知道是哪个线程在调用
  • 线程id: auto mainThreadId = std::this_thread::get_id();s.get_id();
  • 线程暂停: std::this_thread::sleep_for()/sleep_until();需要引入跟时间相关的头文件<chrono>,100毫秒使用std::chrono::milliseconds(100)
  • 对比: 先用主线程执行一次,然后一人一半执行一次。分别打印两次耗时(<ctime>auto begin = clock();),结果比例接近2:1,但不等于,因为开一个线程是挺费时的(包括构造、清理,为环境做准备)。

65、当线程间需要共享非const的资源,(问题引出)

  • 效率最高线程数量: std::thread::hardware_concurrency();返回效率最高的线程数量,但仅仅是个参考,实际情况一般会很复杂(服务器机器不止运行你这一个程序)。
  • 描述: 一千万次计算分为三份,给三个线程去计算总和。这次传入同一个值的引用,同时传入同一个对象的引用,用来自增统计次数。然后就发现统计的次数,和计算的总和,都比正确的值要少。
  • 原因: 变量在做自增操作时分三步:1、写入寄存器;2、寄存器中加1;3、写入内存。

66、(thread的构造和新问题)

  • 最好的方法: 如果没有必要的话,线程间
  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值