当前位置: 首页 > news >正文

[项目][WebServer][TcpServer]详细讲解

  • 单例模式的线程安全
    • 需要双重判空指针,降低锁冲突的概率,提高性能
    • 原因1:
      • 当第一次实例化单例时,可能有多个线程同时到来,并且svr指针为空
      • 这时他们就会去竞争锁,但只有一个线程会最快拿到锁,并且成功实例化出单例对象
      • 但此时如果不加双重判空指针,那些也进了第一层if判断的,仍然会去实例化出对象
    • 原因2:
      • 为了线程安全,必然要加锁,加锁之后再去判空
      • 但每次调用GetInstance()都需要去获得锁,释放锁,效率低下
      • 此时再加一层外层if判空,这样就会避免后续调用GetInstance()时没必要的锁竞争
static const uint16_t PORT = 8090;
static const int BACKLOG = 128;// 单例 -- 饿汉模式
class TcpServer
{
public:static TcpServer* GetInstance(uint16_t port = PORT){static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;if(svr == nullptr) // 双重判空指针,降低锁冲突的概率,提高性能{// 注意线程安全pthread_mutex_lock(&lock);if(svr == nullptr){svr = new TcpServer(port);svr->Init();}pthread_mutex_unlock(&lock);}return svr;}void Init(){Socket();Bind();Listen();LOG(INFO, "TcpServer Init ... Success");}void Socket(){_listenSock = socket(AF_INET, SOCK_STREAM, 0);if(_listenSock < 0){LOG(FATAL, "Socket Error");exit(1);}// 设置端口复用int opt = 1;setsockopt(_listenSock, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));LOG(INFO, "Create Listen Socket ... Success");}void Bind(){struct sockaddr_in local;memset(&local, 0, sizeof(local));local.sin_family = AF_INET;local.sin_addr.s_addr = INADDR_ANY;local.sin_port = htons(_port);if(bind(_listenSock, (struct sockaddr*)&local, sizeof(local)) < 0){LOG(FATAL, "Bind Error");exit(2);}LOG(INFO, "Bind Socket ... Success");}void Listen(){if(listen(_listenSock, BACKLOG) < 0){LOG(FATAL, "Listen Error");exit(3);}LOG(INFO, "Listen Socket ... Success");}int Sock(){return _listenSock;}~TcpServer(){if(_listenSock >= 0){close(_listenSock);}}
private:TcpServer(uint16_t port): _port(port), _listenSock(-1){}TcpServer(const TcpServer&) = delete;
private:uint16_t _port;int _listenSock;static TcpServer* svr;
};TcpServer* TcpServer::svr = nullptr;

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • nnunetv2系列:解压zip文件到nnunet默认路径
  • Windows下Python和PyCharm的应用(二)__快捷键方式的设定
  • 前端框架有哪些?全面解析主流前端框架
  • 深入解析五大 LLM 可视化工具:Langflow、Flowise、Dify、AutoGPT UI 和 AgentGPT
  • 出现 E: Sub-process /usr/bin/dpkg returned an error code (1) 解决方法 (全面分析)
  • [SWPU2019]Web1 超详细教程
  • PMP--一模--解题--1-10
  • 前端网络请求库:Axios
  • Docker中部署.NetCore项目
  • 结构型模式-python版
  • Android12_13左上角状态栏数字时间显示右移动
  • 真正解决微信截图卡住(假死)
  • 聚焦:clicOH 借助 NVIDIA cuOpt 实现最后一英里交付速度 20 倍提升
  • 手机如何执行Python
  • 天童教育:让孩子练习独立思考
  • 【跃迁之路】【477天】刻意练习系列236(2018.05.28)
  • angular组件开发
  • java8 Stream Pipelines 浅析
  • JavaScript新鲜事·第5期
  • JS字符串转数字方法总结
  • learning koa2.x
  • Magento 1.x 中文订单打印乱码
  • MD5加密原理解析及OC版原理实现
  • react-native 安卓真机环境搭建
  • UMLCHINA 首席专家潘加宇鼎力推荐
  • vue的全局变量和全局拦截请求器
  • Work@Alibaba 阿里巴巴的企业应用构建之路
  • Yii源码解读-服务定位器(Service Locator)
  • 浮现式设计
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 王永庆:技术创新改变教育未来
  • 我的业余项目总结
  • 小程序开发中的那些坑
  • 学习JavaScript数据结构与算法 — 树
  • 字符串匹配基础上
  • Nginx惊现漏洞 百万网站面临“拖库”风险
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • 不要一棍子打翻所有黑盒模型,其实可以让它们发挥作用 ...
  • ​Kaggle X光肺炎检测比赛第二名方案解析 | CVPR 2020 Workshop
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • !!【OpenCV学习】计算两幅图像的重叠区域
  • #Linux(帮助手册)
  • #每日一题合集#牛客JZ23-JZ33
  • (1)(1.13) SiK无线电高级配置(六)
  • (pt可视化)利用torch的make_grid进行张量可视化
  • (STM32笔记)九、RCC时钟树与时钟 第一部分
  • (定时器/计数器)中断系统(详解与使用)
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (非本人原创)史记·柴静列传(r4笔记第65天)
  • (附表设计)不是我吹!超级全面的权限系统设计方案面世了
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (一)utf8mb4_general_ci 和 utf8mb4_unicode_ci 适用排序和比较规则场景
  • (一)基于IDEA的JAVA基础10
  • (自用)learnOpenGL学习总结-高级OpenGL-抗锯齿
  • *2 echo、printf、mkdir命令的应用