update blog

This commit is contained in:
lemonchann
2020-02-09 20:01:04 +08:00
parent 2bd246fb4f
commit 3dcbb1bd0a
3 changed files with 69 additions and 62 deletions

View File

@@ -7,18 +7,16 @@ comments: true
author: lemonchann author: lemonchann
--- ---
文章是由自己笔试面试腾讯笔记整理而来,整理的时候又回顾了一遍,中间工作忙断断续续整理了半个月,才完成现在的样子。主要是针对面试的C++后台开发岗位涵盖了大部分C++相关的可能会被问到的技术点,作为面试技术的参考回头查阅 **文章是由笔试面试腾讯笔记整理而来主要是针对面试的C++后台开发岗位涵盖了大部分C++后台开发相关的可能会考察和被问到的技术点。**
这篇笔记是基础C++知识点总结没有过多的阐述后台开发的系统架构和分布式后台服务设计相关还有c++11新特性这些笔试面试也会被问到但不在这篇讨论范围可以关注专栏后面如果有机会再补上。 **自认为这篇笔记比较全面的涵盖了后台开发C++笔试面试大部分知识点,不管你是已经工作准备参加社招,还是在校学生准备参加校招,笔记都可以作为技术面试准备阶段参考查阅,查缺补漏。**
笔记是基础C++知识点总结没有过多的阐述后台开发的系统架构和分布式后台服务设计相关内容以及C++11新特性这些在笔试面试也会被问到但不在这篇讨论范围可以关注我后面有机会补上。
### 阅读提示 ### 阅读提示
文章约12839字阅读时长预计33分钟。建议关注收藏方便回头查阅。 文章约12839字阅读时长预计33分钟。建议关注收藏方便回头查阅。
### 为什么析构函数要是虚函数?
基类指针可以指向派生类的对象多态性如果删除该指针delete []p就会调用该指针指向的派生类析构函数而派生类的析构函数又自动调用基类的析构函数这样整个派生类的对象完全被释放。如果析构函数不被声明成虚函数则编译器实施静态绑定在删除基类指针时只会调用基类的析构函数而不调用派生类析构函数这样就会造成派生类对象析构不完全。所以将析构函数声明为虚函数是十分必要的。
### gdb调试命令 ### gdb调试命令
#### step和next的区别 #### step和next的区别
@@ -27,59 +25,59 @@ author: lemonchann
#### 查看内存 #### 查看内存
(gdb)p &a //打印变量地址 > (gdb)p &a //打印变量地址
(gdb)x 0xbffff543 //查看内存单元内变量 > (gdbx 0xbffff543 //查看内存单元内变量
0xbffff543: 0x12345678 > 0xbffff543: 0x12345678
(gdb) x /4xb 0xbffff543 //单字节查看4个内存单元变量的值 > (gdb) x /4xb 0xbffff543 //单字节查看4个内存单元变量的值
0xbffff543: 0x78 0x56 0x34 0x12 > 0xbffff543: 0x78 0x56 0x34 0x12
#### 多线程调试 #### 多线程调试
(gdb) info threads查看GDB当前调试的程序的各个线程的相关信息 > (gdb) info threads查看GDB当前调试的程序的各个线程的相关信息
(gdb) thread threadno切换当前线程到由threadno指定的线程 > (gdb) thread threadno切换当前线程到由threadno指定的线程
break filename:linenum thread all 在所有线程相应行设置断点注意如果主线程不会执行到该行并且启动all-stop模式主线程执行n或s会切换过去 > break filename:linenum thread all 在所有线程相应行设置断点注意如果主线程不会执行到该行并且启动all-stop模式主线程执行n或s会切换过去
set scheduler-locking off|on\step 默认off执行s或c其它线程也同步执行。on只有当前相称执行。step只有当前线程执行 > set scheduler-locking off|on\step 默认off执行s或c其它线程也同步执行。on只有当前相称执行。step只有当前线程执行
show scheduler-locking 显示当前模式 > show scheduler-locking 显示当前模式
thread apply all command 每个线程执行同意命令如bt。或者thread apply 1 3 bt即线程13执行bt。 > thread apply all command 每个线程执行同意命令如bt。或者thread apply 1 3 bt即线程13执行bt。
#### 查看调用堆栈 #### 查看调用堆栈
(gdb)bt > (gdb)bt
(gdb)f 1 帧简略信息 > (gdb)f 1 //帧简略信息
(gdb)info f 1 帧详细信息 > (gdb)info f 1 //帧详细信息
#### 断点 #### 断点
b test.cpp:11 > b test.cpp:11
b test.cpp:main > b test.cpp:main
gdb attach 调试方法: gdb attach 调试方法:
gdb->file xxxx->attach pid->这时候进程是停止的->c 继续运行 > gdb->file xxxx->attach pid->**这时候进程是停止的**->c 继续运行
#### 带参数调试 #### 带参数调试
输入参数命令set args 后面加上程序所要用的参数,注意,不再带有程序名,直接加参数,如: 输入参数命令set args 后面加上程序所要用的参数,注意,不再带有程序名,直接加参数,如:
(gdb)set args -l a -C abc > (gdb)set args -l a -C abc
#### list命令 #### list命令
list linenum  显示程序第linenum行的周围的程序 > list linenum  //显示程序第linenum行的周围的程序
list function  显示程序名为function的函数的源程序 > list function  //显示程序名为function的函数的源程序
@@ -91,23 +89,23 @@ list function  显示程序名为function的函数的源程序
ln -s 源文件 目标文件, ln -s / /home/good/linkname链接根目录/到/home/good/linkname ln -s 源文件 目标文件, ln -s / /home/good/linkname链接根目录/到/home/good/linkname
1、软链接就是“ln s 源文件 目标文件”只会在选定的位置上生成一个文件的镜像不会占用磁盘空间类似与windows的快捷方式。 1. 软链接就是“ln s 源文件 目标文件”只会在选定的位置上生成一个文件的镜像不会占用磁盘空间类似与windows的快捷方式。
2、硬链接ln源文件目标文件没有参数-s 会在选定的位置上生成一个和源文件大小相同的文件,无论是软链接还是硬链接,文件都保持同步变化。 2. 硬链接ln源文件目标文件没有参数-s 会在选定的位置上生成一个和源文件大小相同的文件,无论是软链接还是硬链接,文件都保持同步变化。
### 函数指针 ### 函数指针
函数指针 int (*func)(int, int) int (*func)(int, int) //函数指针
函数指针数组 int (*funcArry[10])(int, int) int (*funcArry[10])(int, int) //函数指针数组
const int* p; 指向const int的指针 const int* p; //指向const int的指针
int const* p; 同上 int const* p; //同上
int* const p; const指针 int* const p; //const指针
@@ -438,7 +436,13 @@ list是由双向链表实现的因此内存空间是不连续的。
class LayerManager : public ILayerManager; class LayerManager : public ILayerManager;
#### 为什么析构函数要是虚函数?
基类指针可以指向派生类的对象多态性如果删除该指针delete []p就会调用该指针指向的派生类析构函数而派生类的析构函数又自动调用基类的析构函数这样整个派生类的对象完全被释放。如果析构函数不被声明成虚函数则编译器实施静态绑定在删除基类指针时只会调用基类的析构函数而不调用派生类析构函数这样就会造成派生类对象析构不完全。所以将析构函数声明为虚函数是十分必要的。
#### 覆盖虚函数机制 #### 覆盖虚函数机制
@@ -446,39 +450,22 @@ class LayerManager : public ILayerManager;
本,这里可以使用作用域操作符: 本,这里可以使用作用域操作符:
```c++
Item_base *baseP = &derived; Item_base *baseP = &derived;
// calls version from the base class regardless of the dynamic type // calls version from the base class regardless of the dynamic type of baseP
of baseP
double d = baseP->Item_base::net_price(42); double d = baseP->Item_base::net_price(42);
```
这段代码强制将 net_price 调用确定为 Item_base 中定义的版本,该调用 这段代码强制将 net_price 调用确定为 Item_base 中定义的版本,该调用
将在编译时确定。 将在编译时确定。**只有成员函数中的代码才应该使用作用域操作符覆盖虚函数机制。**
只有成员函数中的代码才应该使用作用域操作符覆盖虚函数机制 **为什么会希望覆盖虚函数机制?最常见的理由是为了派生类虚函数调用基类中的版本。**在这种情况下,基类版本可以完成继承层次中所有类型的公共任务,而每个派生类型只添加自己的特殊工作
为什么会希望覆盖虚函数机制?最常见的理由是为了派生类虚函数调用基 例如,可以定义一个具有虚操作的 Camera 类层次。Camera 类中的 display函数可以显示所有的公共信息派生类如 PerspectiveCamera可能既需要显示公共信息又需要显示自己的独特信息。可以显式调用 Camera 版本以显示公共信息,而不是在 PerspectiveCamera 的 display 实现中复制 Camera 的操作。
类中的版本。在这种情况下,基类版本可以完成继承层次中所有类型的公共任务, 在这种情况下,已经确切知道调用哪个实例,因此,不需要通过虚函数机制。派生类虚函数调用基类版本时,必须显式使用作用域操作符。如果派生类函数忽略了这样做,则函数调用会在运行时确定并且将是一个自身调用,从而导致无穷递归。
而每个派生类型只添加自己的特殊工作。例如,可以定义一个具有虚操作的 Camera 类层次。Camera 类中的 display
函数可以显示所有的公共信息,派生类(如 PerspectiveCamera可能既需要显
示公共信息又需要显示自己的独特信息。可以显式调用 Camera 版本以显示公共
信息,而不是在 PerspectiveCamera 的 display 实现中复制 Camera 的操作。
在这种情况下,已经确切知道调用哪个实例,因此,不需要通过虚函数机制。
派生类虚函数调用基类版本时,必须显式使用作用域操作符。
如果派生类函数忽略了这样做,则函数调用会在运行时确定并
且将是一个自身调用,从而导致无穷递归。
@@ -530,6 +517,8 @@ struct Derived : Base
设计派生类时,只要可能,最好避免与基类数据成员的名字相同 设计派生类时,只要可能,最好避免与基类数据成员的名字相同
#### 类成员函数的重载、覆盖和隐藏区别? #### 类成员函数的重载、覆盖和隐藏区别?
a.成员函数被重载的特征: a.成员函数被重载的特征:

View File

@@ -1,17 +1,17 @@
--- ---
layout: post layout: post
title: "redis分布式锁3种实现方式分析" title: "redis分布式锁3种实现方式对比分析总结"
date: 2020-1-28 date: 2020-1-28
tags: [后台开发] tags: [后台开发]
comments: true comments: true
author: lemonchann author: lemonchann
--- ---
大家春节在家抢红包玩的不亦乐乎,简单的抢红包动作看起来非常简单实际上要做好这个服务特别是money相关服务是不允许出错的想想看每个红包的数字都是真金白银要求服务的鲁棒性非常高背后包含很多后台服务技术细节可以写 大家春节在家抢红包玩的不亦乐乎,抢红包服务看起来非常简单实际上要做好这个服务特别是money相关服务是不允许出错的想想看每个红包的数字都是真金白银要求服务的鲁棒性非常高背后包含很多后台服务技术细节。
<!-- more --> <!-- more -->
抛砖引玉,今天就来说说其中一个技术细节,也是在我的上一篇文章[Linux后台开发C++学习路线技能加点](https://zhuanlan.zhihu.com/p/102048769)中提到但没展开讲的高并发编程中的**redis分布式锁**。 抛砖引玉,今天就来说说其中一个技术细节,也是在我一篇文章[Linux后台开发C++学习路线技能加点](https://zhuanlan.zhihu.com/p/102048769)中提到但没展开讲的高并发服务编程中的**redis分布式锁**。
这里罗列出**3种redis实现的分布式锁**,并分别对比说明各自特点。 这里罗列出**3种redis实现的分布式锁**,并分别对比说明各自特点。
@@ -76,7 +76,7 @@ set用法参考[官方文档](https://redis.io/commands/set)
- `NX` Only set the key if it does not already exist. - `NX` Only set the key if it does not already exist.
- `XX` Only set the key if it already exist. - `XX` Only set the key if it already exist.
- `EX` *seconds* 设置键key的过期时间单位时秒 - `EX` *seconds* 设置键key的过期时间单位时秒
- `PX` *milliseconds* 设置键key的过期时间单位毫秒 - `PX` *milliseconds* 设置键key的过期时间单位毫秒
- `NX` 只有键key不存在的时候才会设置key的值 - `NX` 只有键key不存在的时候才会设置key的值
- `XX` 只有键key存在的时候才会设置key的值 - `XX` 只有键key存在的时候才会设置key的值

View File

@@ -155,6 +155,24 @@ author: lemonchann
## TCP/IP协议
目前网络通信中应用最广泛的协议就是IP TCP协议后面Unix提供的TCP套接字也是基于协议实现所以很有必要系统的学习 TCP/IP 协议。
#### 推荐书:
大学的计算机网络教程
[《TCP/IP详解 卷1协议》](https://book.douban.com/subject/1088054/)
[《TCP/IP详解 卷2实现》](https://book.douban.com/subject/1087767/)
[《TCP/IP详解 卷3TCP事务协议、HTTP、NNTP和UNIX域协议》](https://book.douban.com/subject/1058634/)
这几本书很厚可以先看卷1、卷3
## Linux网络编程套接字 ## Linux网络编程套接字
在同一台机器上进程间的通信IPC有多种方式可以是通过**消息队列、FIFO、共享内存**等方式。网络编程套接字是指:分布在不同机器上的程序通过系统提供的网络通信接口,跨越网络将不同机器上的进程连接起来,实现跨机器的网络通信。一般有**UDP套接字、TCP套接字、Unix Domain当然如果你是通信从业者对SCTP套接字肯定也不会陌生。** 在同一台机器上进程间的通信IPC有多种方式可以是通过**消息队列、FIFO、共享内存**等方式。网络编程套接字是指:分布在不同机器上的程序通过系统提供的网络通信接口,跨越网络将不同机器上的进程连接起来,实现跨机器的网络通信。一般有**UDP套接字、TCP套接字、Unix Domain当然如果你是通信从业者对SCTP套接字肯定也不会陌生。**