一个二本本科生如何才能进入腾讯,阿里,百度这些大厂?

Posted analogous_love

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个二本本科生如何才能进入腾讯,阿里,百度这些大厂?相关的知识,希望对你有一定的参考价值。

我这边是大厂技术岗位。

这里有一份拿了腾讯、阿里、百度大厂的 offer 的同学的经验分享录象。

录像获取地址(仅供个人学习使用,不得上传至网络或者作为盈利目的):

链接: https://pan.baidu.com/s/1zHBGWwtiXLMJvhf5_vnR8w 密码: t8nh

我知道很多应届同学学历不好,但都想进大厂。那么当初我给了他什么学习建议呢?今天我就来说说。

一、思想层面

首先,要解决思想层面上的问题。

不要给自己的人生设置上限。很多同学因为这样或者那样的原因,高考没考好,最近进入了一个不太如意的大学。但是请不要自怨自艾,高考虽然是人生很关键的机会,但绝对不是唯一的机会。所以,学校不好,只要你能迎头赶上,最后通过自己的努力也未尝实现不了目标。

所以不要觉得自己考的学校不行,就处处不如人。即使你是非科班,只要努力加上正确的方法,最终一定能成功的。

其次,要用行动。这种行动不是做给别人看的。接下来学习、看书。不在乎你看多少本书,学习多长时间,而是你每次理解、学会了多少,每天甚至每周有点进步,时间久了,也可以取得长足的进步。

最怕的就是还没看一本书,朋友圈到处打卡;还没行动,人尽皆知。面试过一些同学,简历上写上看了一堆经典书籍,最后一问啥都说不清楚。记住,行动是一步一个脚印。这期间可以允许你稍微偷点懒,但是一定是这段时间比上一段时间有提高,自我安慰式的努力和自我安慰式的提高,只注重形式不注重结果的行动是没任何意义的。

这也是为什么每次有球友找我做辅导时,我会先给你解决思想上的困难。业精于勤荒于嬉,行成于思毁于随。

二、学习方法

解决了思想上的问题,下面是行动上的问题了。

1. 第一阶段

无论你是科班还是非科班,建议你一定要学好 C 语言,它应该作为你必须掌握好的语言。你要熟悉 C 语言的基本语法,包括:

  • 顺序、条件、循环三大控制语句

  • C 中几大基元数据类型的用法

  • 熟悉掌握数组的用法

  • 熟练掌握指针的用法

  • 熟练掌握结构体、枚举、联合等数据类型的用法

  • 熟练使用常用 C 库函数,如控制台输入输出流、字符串操作、文件操作、时间函数等等

以上阶段算是启蒙阶段,在这个阶段,是基础编程语法的学习,当然,你不仅仅要掌握这些基本语法,你还要反复练习。

这个阶段可以推荐一本非常的图书《C 语言设计 现代方法》(文末有获取方式),这本书在国外是作为大学教材的,引进到国内翻译的也很棒。

2. 第二阶段

如果你想毕业后进大厂,从这时开始学习算法和数据结构。学习算法和数据一定不能急功近利,算法和数据结构的知识一定要作为一个长期的学习目标。

对于非科班的同学,由于没有像科班同学那样接受到系统的学习,一定要找一两本经典书籍系统地学习下常见的算法理论、思想和常用的数据结构知识。等熟悉了这块的知识,再适当地刷一些算法题目或者做一些算法练习。

如果你觉得算法和数据结构很吃力,推荐一下《算法(第四版)》(文末有获取方式)。

面试大厂之前要适当刷一些题目,推荐leetcode 和 《剑指 offer》(文末有获取方式)。

3. 第三阶段

大学四年(研究生三年)说长不长,说短也不短。接下来就挨个补相应的基础知识了。如果你是非科班,也建议自己找点经典的书籍系统地学习一下。下面挨个说一下这几大方面的基础知识。

3.1 编程语言方面

你可以根据你的兴趣自由选择 C++ 或者 Java。这里以 C++ 为例,需要强调的是,既然是学习,请抛弃各种总结经验技巧的面经,逐个掌握 C++ 语言的各个语法,包括但不局限于:

  • 指针和引用的概念

  • 指针与内存关系

  • 程序编译过程,静态链接库和动态链接库

  • static、const、#define的用法和区别

  • C和C++区别

  • 内存中的栈和堆分配

  • 面向对象理解

  • 访问限定符 public/protected/private

  • 构造函数/析构函数/拷贝构造

  • 多态

  • 虚函数与纯虚函数、虚函数实现机制、虚函数表

  • 继承原理、虚继承、菱形继承

  • new/delete和malloc/free

  • 重载、重写和覆盖

  • 类型转换方式

  • RAII 与 pimpl 惯用法

  • 内存溢出和内存泄漏

  • STL标准模板库

  • 迭代器、空间配置器理解

  • 常用容器特点、用法以及底层实现vector、list、deque、set、map、unorderedmap

C++11/14/17 新标准也慢慢成为主流,这块也要熟悉,要熟悉新标准常用的语法与新功能,包括:另外,时至今日,你一定要熟悉 C++11/14/17 常用的语言特性和类库,这里简单地列一下:

  • 左值/右值/std::move/std::forward

  • 统一的类成员初始化语法与 std::initializer_list

  • 注解标签(attributes)

  • final/override/=default/=delete 语法

  • auto 关键字

  • Range-based 循环语法

  • 结构化绑定

  • stl 容器新增的实用方法

  • std::thread

  • 线程局部存储 thread_local

  • 线程同步原语 std::mutex、std::condition_variable 等

  • 原子操作类

  • 智能指针类

  • std::bind/std::function

C++11/14 网上的资料已经很多了,C++17 的资料不多,重点掌握的还是 C++11 引入的各种实用特性,这就给读者推荐一些我读过的书:

《深入理解 C++11:C++11 新特性解析与应用》 《深入应用 C++11:代码优化与工程级应用》 《C++17 完全指南》 《Cpp 17 in Detail》

(文末有获取方式)

3.2 熟悉编程语言相关的开发工具链

熟悉该语言的相关的 IDE 开发环境,Windows上我推荐 Visual Studio,Mac 上可以使用Subline 或者VSCode,如果你最终的程序需要在 Linux 跑,你需要熟悉 cmake/make/gcc/g++/gdb 工具链,vim 的基本操作也要熟悉,但绝对不要直接在 vim 中写代码,纯属浪费时间,实际企业级开发也没人会这么做。这里强调一下,如果可能,至少要熟悉 Visual Studio 和 gdb 调试,调试需要掌握哪些内容呢?

建议掌握:

  • 如何启动和结束调试

  • 如何添加/删除/启用/禁用断点(包括普通断点、条件断点和数据断点)

  • 如何查看当天断点下的调用对战

  • 如何查看程序运行过程中的线程信息(这块可以放到下文再学)

  • 如何查看某个变量的内存值

掌握了一门编程语言加其开发的工具链,你的想法就可以通过动手变为现实了。熟悉了 C/C++ 语言和其相关的开发工具链,接下来你可以根据你的兴趣学习相关的开发知识了。

3.3 熟悉相关的操作系统的 API 接口

很多人说,操作系统的 API 接口不用刻意学习,根据我个人的经验,我反对这一观点,操作系统的很多 API 涉及到很多操作系统原理和使用技巧,绝非是想用的时候去查一查就可以了。就和开卷考试一样,如果不熟悉,且不说不知道如何查、在哪查,就算查到了,是否可以用好又是另外一回事了。

Linux 系统推荐学习《Linux 系统编程》,Windows 系统推荐《Windows 程序设计(第五版)》和 《Windows 核心编程》(文末有获取方式)。

以下是来自两位读者的提问:

  1. 请教个问题哈,我需要刚打开应用程序时,在View的OnDraw内创建一个线程,每次当我点击菜单按钮产生对话框后,终止View类中OnDraw内的这个线程,对话框退出,又创建这个线程,是不是得弄个线程池。。或者是使用SuspendThread和ResumeThread来控制吗?

  2. 单个 epoll + 线程池与每个线程一个 epoll 这两种架构哪个更适合大量短连接的场景?

这两个问题都反映出提问的读者对基础的原理含糊不清,我贴出这两个问题,就是想告诉你,学习操作系统的接口不仅是学习相关操作系统 API,同时也是在培养自己的动手和实践能力。常用的操作系统 API 并不多,以多线程相关的为例,Windows 系统提供的线程同步原语常用的有临界区、Event、互斥体、信号量等,Linux 常用的有互斥体、读写锁、信号量和条件变量,掌握这些并不困难,你只要花一周时间挨个地学习联系一下,很快就能掌握。

熟悉了常用操作系统的 API 之后,你就可以自由地写出自己想要的程序了,这个时候处于初级的通透状态,例如,你可以随手写出这样一个功能的程序:

主线程创建一个新的工作线程,等待工作线程获取系统时间后写入文件;主线程从文件中读取时间内容显示出来。

这个例子中,我们用到了创建线程的 API、线程等待与通知 API、获取系统时间的 API、显示到控制台的 API

在 Windows 上,我们用到:

  1. CreateThread

  2. WaitForSingelObject

  3. GetSystemTime

  4. CreateEvent/SetEvent

  5. std::cout

在 Linux 上,我们可以使用:

  1. pthread_create

  2. pthread_mutex_init/pthread_cond_init/pthread_cond_destroy/pthread_cond_wait

  3. time

  4. std::cout

这么一分析是不是觉得一下子清晰起来,因为 C/C++ 这么编程语言不是功能完备性的,如果 C/C++ 的 C 库或者 stl 本身没有提供这些功能,你不得不使用操作系统的 API。

如果你掌握到这个阶段,恭喜你,你已经可以去胜任中小企业的 C/C++ 开发了。所以,我推荐的这条路线,如果你认真学习,保底能让你找到一份小公司的 C++ 开发工作的。

3.4 熟悉多线程编程

这块与上文有一点重叠,我们再次说一下。多线程知识,你需要掌握理解线程与进程的关系、熟练使用常用的线程同步技术。推荐的一种学习方式,就是找一个开源项目,使用调试器跑起来,然后看看这个进程有多少线程,每个线程在何时被创建,每个线程的作用是什么,线程之间如何通信的。这也是上文建议你熟练掌握调试器的原因。

多线程编程目前网上我没有见过系统地、详尽的教材,于是我自己写了一个,我把它放在我的图书《C++ 服务器开发精髓》的第三章中去了,可以给大家贴下目录:

第3章 多线程编程与资源同步.. 159

3.1 线程的基本概念及常见问题... 159

3.1.1 主线程退出,支线程也将退出吗... 159

3.1.2 某个线程崩溃,会导致进程退出吗... 160

3.2 线程的基本操作... 160

3.3 惯用法:将C++类对象实例指针作为线程函数的参数... 178

3.4 整型变量的原子操作... 184

3.4.1 为什么给整型变量赋值不是原子操作... 185

3.4.2 Windows平台上对整型变量的原子操作... 186

3.4.3 C++ 11对整型变量原子操作的支持... 187

3.5 Linux线程同步对象... 190

3.5.1 Linux互斥体... 190

3.5.2 Linux信号量... 198

3.5.3 Linux条件变量... 202

3.5.4 Linux读写锁... 208

3.6 Windows线程同步对象... 217

3.6.1 WaitForSingleObject与WaitForMultipleObjects函数... 217

3.6.2 Windows临界区对象... 219

3.6.3 Windows Event对象... 224

3.6.4 Windows Mutex对象... 229

3.6.5 Windows Semaphore对象... 231

3.6.6 Windows读写锁... 235

3.6.7 Windows条件变量... 238

3.6.8 在多进程之间共享线程同步对象... 243

3.7 C++ 11/14/17线程同步对象... 244

3.7.1 std::mutex系列... 244

3.7.2 std::shared_mutex. 248

3.7.3 std::condition_variable. 253

3.8 如何确保创建的线程一定能运行... 256

3.9 多线程使用锁经验总结... 258

3.10 线程局部存储... 262

3.10.1 Windows的线程局部存储... 262

3.10.2 Linux的线程局部存储... 264

3.10.3 C++ 11 的 thread_local 关键字... 267

3.11 C库的非线程安全函数... 268

3.12 线程池与队列系统的设计... 270

3.12.1 线程池的设计原理... 270

3.12.2 环形队列... 275

3.12.3 消息中间件... 275

3.13 纤程(Fiber)与协程(Routine)... 277

3.5 熟悉操作系统原理

操作系统原理无论是面试还是自我提高的五大基础之一,我的建议学习操作系统知识时,不一定要看完所有操作系统书籍,但一定将一些基础概念(如进程、线程、内存模式等)看懂、理清。Tanenbaum.A.S《现代操作系统》(文末有获取方式)是一本讲解操作系统理论不错的书,作者 Tanenbaum.A.S 是 Linux 内核创始人 Linus Torvalds 的老师。

你如果还有时间强烈推荐看看俞甲子的《程序员的自我修养:链接、装载与库》(文末有获取方式)。这本书同时涉及到了 Windows 和 Linux 两个操作系统平台,用各种辅助工具剖析了程序从源码到二进制文件再到装载到进程地址空间里面的各个细节,甚至连进程地址空间中的堆结构、栈结构也分析得清清楚楚,同时也分析了 C Runtime(CRT)、glibc 这样的操作系统接口库的原理和执行逻辑,是一本实实在在帮你实战操作系统原理的好书。

当然,学有余力的同学,可以进一步了解一些关于操作系统的模式(如实模式、保护模式)、系统的启动与初始化、虚拟内存与物理内存、内存分表分页机制、进程与线程的调度算法等知识。

3.6 计算机网络

学习计算机网络要从以下三个方面学习:

3.6.1 计算机网络理论知识

计算机网络编程你需要掌握基础的如三次握手和四次挥手的过程以及各个状态值,我建议使用 tcpdump 命令实际抓下包就一目了然了,然后就是网络分层,各层的用途,重点熟悉下 TCP/IP 层相关的知识,还有就是 TCP/UDP 的区别,TCP 的滑动窗口机制、拥塞控制算法、TCP 的保序、重传、确认机制。

学习这些知识的时候,一定不要死记硬背,注重理解。我近来面试了一部分学历学校非常好的同学,然而,在问到这块的知识时却大失所望。例如,有的同学只是单纯把三次握手背下来了,我稍微变通一下他就不知道怎么回答了:

  1. 如果连接一个目标主机不存在的 IP 地址握手过程是怎样的?连接一个目标 IP 存在但是端口号不存在的主机又是怎样的握手过程呢?

  2. A 机器上的进程与 B 机器上的进程进行网络通信,分别经历了哪些网络层。

3.6.2 Socket 编程

Socket 编程你需要先掌握常用的 Socket API,包括但不局限于:

常用 Berkeley Sockets API 一览表

学习这些 Socket API 的时候,不是让你单纯地记忆这些函数的参数,而是掌握每一个函数的重难点。

例如:

  1. 如何将一个 socket 设置成非阻塞模式

  2. 阻塞模式下,send 和 recv 函数行为是什么样子的?非阻塞模式下 send/recv 的返回值分别是什么?

  3. 客户端发起连接时,如何主动指定通过本地某个端口号去连接?bind 函数如果端口号设置为 0 是什么行为?

  4. listen 函数的 backlog 参数用途是什么?

  5. 如何实现异步的 connect 函数?

  6. accept 函数调用时,三次握手是否已经完成?

  7. 如何实现半关闭状态?

  8. nagle 算法的用途是什么?

  9. select 函数的第一个参数怎么设置?select 函数的超时参数如果设置为 NULL 是什么行为?

接着要重点学习下常用的网络模型:

  1. Windows 上常用的网络模型有 select、WSAEventSelect、WSAAsyncSelect、完成端口模型;

  2. Linux 上常用的网络模型 select、poll、epoll,epoll 需要重点关注的是水平模式和边缘模式。

当然,也建议一定要理解,不要死记硬背。C++ 的同学来面试的时候,我会给他们准备如下面试题:

  1. epoll 边缘模式下,某次读取了某个 socket 上的部分数据,下次是否会出发读事件?如果此时又来了一个字节的新数据,是否会触发读事件?

  2. epoll 边缘模式建议尽量一次把数据读完,怎样判断当前数据已经读完?

  3. epoll 边缘模式下,对于写事件应该如何处理?

接着还要熟悉 TCP 协议的流式特性,如何解决粘包问题;还要掌握常见的网络协议格式,像 HTTP、FTP、POP3/SMTP/WebSocket协议的格式都建议熟练掌握。

以 HTTP 协议为例,HTTP 协议包的格式是什么样的,包头和包体如何分界的,GET 与 POST 请求的数据分别放在 HTTP 包的什么位置,如果放在包体中,如何知道包体的数据有多长。

3.6.3 常用网络命令

学习了常用的网络命令,可以用来排查网络故障与定位问题,反过来,也可以加深对网络理论知识的理解,建议掌握以下命令:ifconfig、ping、telnet、netstat、lsof、nc、curl、tcpdump。

掌握了这些命令要做到学以致用,例如现在某个服务器连接不上,如何使用这些命令判断是自己网络的问题还是目标主机的问题;开发了一个服务器程序,手头上没有可用的客户端,如何使用 nc 命令模拟一个;或者反过来,开发了一个客户端程序,如果用 nc 模拟一个服务器端用于测试。

推荐《TCP/IP 网络编程》和《Linux 高性能服务器编程》(文末有获取方式)。

3.7 数据库

数据库需要掌握的基础知识有:

  1. 熟悉基本 SQL 操作 包括增删改查(insert、delete、update、select语句),排序 order,条件查询(where 子语句),限制查询结果数量(LIMIT语句)等

  2. 稍微高级一点的 SQL 操作(如 Group by,in,join,left join,多表联合查询,别名的使用,select 子语句等)

  3. 索引的概念、索引的原理、索引的创建技巧

  4. 数据库本身的操作,建库建表,数据的导入导出

  5. 数据库用户权限控制(权限机制)

  6. mysql 的两种数据库引擎的区别

  7. SQL 优化技巧

以上属于对开发的基本的数据库知识要求,你可以找一本相关入门级的数据库图书,我推荐一下《《MySQL技术内幕(第5版)》。

高级开发除了以上要求还要熟悉高可用 MySQL、主从同步、读写分离、分表分库等技术,这些技术的细节一定要清楚,它们是你成为技术专家或者高级架构的必备知识。我们在实际面试时,在讨论高可用服务服务方案时,很多面试者也会和我们讨论到这些技术,但是不少面试者只知道这些技术的大致思想,细节往往说不清楚,细节不会就意味着你的高可用方案无法落地,企业需要可以落地的方案。

这些技术我首推《高性能 MySQL》这本书,这本书高级开发者一定要通读的,另外还有 2 本非常好的图书也推荐一下:一本是《MySQL 排错指南》,读完这本书以后,你会对整个“数据库世界”充满了清晰的认识;另外一本是《数据库索引设计与优化》,这本书读起来非常舒服,尤其是对于喜欢算法和数据结构的同学来说。

(上文数据库书籍文末有获取方式)

3.8 汇编

如果你熟练掌握汇编,你就比其他人多很多优势,你会能透彻地知道你写的每一行 C/C++ 代码背后的机器指令的效率。无论是做安全工程还是自己技术提升上都是非常不错的。这里推荐一本王爽老师的《汇编语言(第 3 版)》(文末有获取方式),这本书不厚,语言通俗易懂,你也不用刻意去记忆,基本上当小说书看一下就能很快看完了。汇编实战类图书还有另外一本《老码识途:从机器码到框架的系统观逆向修炼之路》(文末有获取方式)。我个人是非常喜欢这本书的。当年读这本书的时候,真的有一种“笑看妻子愁何在?漫卷诗书喜欲狂”的感觉。

3.9 代码规范与风格优化

在你学习的过程中,请一定要认真对待自己每一个变量名、函数名,养成良好的代码习惯。我学生时代花了大量时间去学习一些教人写出优美风格的代码书籍、资料、源码,在你还是个小白的时候,要认真精读一些优秀代码,不仅要学习它们的整体设计思路,还要学习它们的代码风格和细节。这里推荐《程序设计实践》《代码整洁之道》(文末有获取方式)这两本书,特别是《程序设计实践》,强烈建议学生朋友看一下,能大幅度地提高你实际编码的技巧和编码风格。

三、你可能存在的一些疑问

有同学会问那像分布式、消息中间件等要不要掌握?很多大厂都有这样的要求。这个我可以明确地告诉大家,这些对于应届生来说,都不是必要的条件。应届生主要看基础,大厂对算法和数据结构考察是重中之重;小厂要求你能上手干活,会很在乎你实际的编码调试能力,和多线程、网络编程、数据库等方面的能力。

四、写在最后的话

以上就是那天我给这位同学的建议。 好在,两年过去了,天道酬勤,功不唐捐,一位二本的同学逆袭拿到了大厂的 offer,在毕业之际为自己的职业生涯开了一个好头,祝这位同学发展越来越好。

作为一名过来人的老学长,我码这么多字,希望想做好开发的学弟学妹们,勿在浮沙筑高台。如果你现在还是学生,你有大把读书的机会,一定要珍惜大好读书时光。工作年限不长的同学,也应该尽快在工作的早些年把基本功打扎实。三十岁以后面临着工作、家庭等各种问题,你可能再不能心无旁骛地去学习和提升了。

所以前期的积累很重要,毕竟选择技术这条路,提高技术是升职加薪改善生活水平最直接的方法。

最后上文中的书单,可以在这里获取:

计算机必看经典书籍(含下载方式)​

原创不易,如果有帮助,记得点赞哦~

以上是关于一个二本本科生如何才能进入腾讯,阿里,百度这些大厂?的主要内容,如果未能解决你的问题,请参考以下文章

一个二本本科生如何才能进入腾讯,阿里,百度这些大厂?

普通二本如何才能进入腾讯阿里百度这些大厂做前端开发?

8年Android老司机的面经,教你如何进入阿里腾讯华为等大厂

被大厂拒绝后,沉淀两年,终于拿下(腾讯阿里百度等offer)

某拼多多程序员嘲讽阿里员工学历不如他们!平均不过普通本科!

985本科毕业,3年半Android经验面试大厂汇总(阿里腾讯爱奇艺均已offer)