[回首来时路]

[回首来时路]

作为一名开发人员, 注重的是的学习积累和实践.
从2005年工作至今, 一晃六年过去了, 做过些项目, 也有了些经验.
从各种渠道吸取的知识对我帮助颇大, 加上几年没有对外发布技术文章(本人有写手札的习惯, 几乎碰过的每个问题, 都有研究报告设计文档, 实现模型源代码等等), 促使我写些东西总结, 也许同时可以为大家提供一些参考.
由于多数研发成果与工作有关(都是已上线的产品), 所以具体技术只限于思想框架(请勿索要源代码).

 

致谢
衷心感谢曾经帮助过我的前辈和同仁们, 谢谢你们的教诲!

 

核心构架 : Linux上的XMPP服务集群
05年, 公司决定要做一个基于XMPP协议的, 支持语音服务的IM(即时通讯)产品, 实现PC/智能手机平台的互通.
作为新人, 承蒙研发部老大(CTO, Z总)的信任, 担当了一些比较重要的工作.
在他的指导下, 完成了服务器的一些压力测试.
主要是模仿大量客户端完成自动注册, 登陆, 添加/删除好友, 发送在线消息, 离线消息, 注销等等.
然后由耗时, 发送成功/失败, 作汇总统计, 由此测试服务器的负载极限, 为采购服务器提供依据.
然后写一些文档, 不过是诸如开发工具的配置等等, IDE是Magic C++, 一个在win32下远程GDB的IDE, 用起来和VC6很类似, 调试起来直观了不少.

 

用户注册模块
负载问题有个初步依据, 接下来就是注册.
为实现用户ID的唯一性和可控性, 采取了类似螣讯QQ号的ID.
基本需求有2点, 一要有很大的区间来保证用户容量, 二是能预知和调整ID的长度, 起始值(保留短ID靓号), 具有唯一性.
这就意味着要找到一个合适的散列函数f(x),映射出符合要求的y.
确定了算法, 接下来就是实现. 当时的考虑是, 需要从网站可以注册, 发手机短信也可以注册.
初看起来, 问题很简单:
1. 写个WEB界面的网站, 后台处理POST表单操纵数据库.
2. 手机短信收发服务花的时间要长点, 因为毕竟是7x24小时的不间断服务, 要仔细点.
但是, 细节是魔鬼, 需求也在改变和细化.
例如, 在注册过程中, 要是保留一些符合条件的靓号怎么办([xx]888|666[xx] [xx]345[xx]...)?
如何处理恶意请求,恶意注册?
相同手机号在一定时间内注册号码有个数限制怎么办?
如何封杀某些区段和黑名单手机号?
如何自动检测短信服务运行状态?
如果发短信的猫出现异常(SIM卡欠费)等等, 怎样自动提醒管理员?
......
这些都需要解决.
记得刚开始测试时, 很容易有CORE DUMP, 然后不得不PUTTY上去, 手动GDB这些CORE, 查看现场上下文, 调用序列等等来找到问题.
好在上学时有些LINUX基础, 一个多星期下来就基本可以运作了.

 

网站(Web和Wap)的用户注册、登录、下载模块
SMS Push / Recv Service稳定后, 对于PC用户和爱好手机浏览用户, 应该有个更方便的接口. 于是, 按照同样的处理流程和逻辑, 开始了网站相关模块的开发.
好在周围同事中也有不少多年WEB开发的经验, 在学习了几天的PHP后, 实现了模块功能. 然后按照WML的WAP协议, 手机上也可以浏览注册板块了.
而后需要解决的就是登录验证码的动态生成(加入扰乱元素), SESSION的有效验证, 防止重复提交等问题.
上线后, 我开始常常重构/优化系统, 把数据库操作独立一个层, 之上业务逻辑一个层, 事件通知谐调层, UI层, 这样就初步达到了UI和底层分离的目的. (后来,我才发现MS为同样目的开发了MVC框架, 如今的WEB开发高效多了)
下载模块, 要自动根据用户的手机型号来引导到相应页面, 下载对应版本. 同时还要做分类统计, 由此可以知道用户使用的手机型号分布和对应平台, 型号的下载次数, 作为市场统计的依据.
(那时候手机的HTTP HEADER中可以知道手机号, 手机类型, 浏览器型号等等, 直到07年, 中移动封杀这些信息, 大量SP和WAP网站倒闭, 被称为"中国互联网的严冬", 后来我测试过, 除了forward等信息, 用户信息被过滤, 网站就再也拿不到了)

 

WinCE上的客户端
写的这些服务重构了, 上线了, 维护工作量就相对少了很多. Symbian / Win32 / Java平台又都没抽不出人来. 所以, 还是我来完成吧, 于是, 我打开EVC, New一个新Project ...
客户端平台是POCKET PC和SMART PHONE, 区别是一个支持触屏, 一个是键盘.
功能是要做成支持GPRS NET/WAP拨号, 断线检测/重连, 文本/实时语音/附件这3种消息的发送接收, 播放, 查看, 存储, 删除, 转发(本地信息存储, 用的是一个文件型数据库. 代码很小, 可以集成在自己的应用程序里).
当时在写WAP拨号, 我终于体会到了ISP强大: 好好的TCP连接, 如果用WAP方式拨号上网, 实际就是HTTP代理, 手机只能通过10.0.0.172(网关), 用HTTP代理和外界通讯.
就是说, 要发送10个字节的信息, 网络上要发送上百字节的内容, 发送给网关, 网关转发给你想通信的主机, 然后再代理回来给你.
Wow, 具有空前的不实时性, 很低的数据信息的有效负载率, tricky的连接保持时间等等问题.
著名的 Connection : Keep-Alive就是其中之一. 因为各地网关行为的不同(有时网关调整参数, 升级系统), 都会导致WAP方式通讯不正常, 无法登录等等问题.
开发人员不得不面对: Keep-Alive这个Header, 加, 还是不加?

 

手机上的客户端界面
其实主界面就是多个可左右滚动切换的视图.
比较重要的是联系人页面和消息页面. 想象一下QQ, 消息来了, 要有消息通知, 由于语音消息有自动播放选项, 这个还要特殊处理, 包括静音, 离开, 免打扰状态下, 这时候别人给你说话, 是不是自动播放出来等等.
还是拿QQ来做比方, 联系人树形结构要完全自绘, 要美观, 头像缩略图啦, 好友签名啦, 好友昵称, 你对好友的注释名称切换, 排序啦, 好友上线通知啦, 一个都不能少.
问题是要维护2套代码, Smart Phone 和 Pocket PC, 保持界面, 逻辑相同, 工作量就开始大了, 一些通用底层模块, 只用统统放到独立DLL里, 而且和UI分离.
好在后来Visual Studio 2005上MFC可以用到智能设备上, 再加上WIN32平台的TJ老兄写的通用库, 大家底层能共用的就公用.
模块化后, 日子好过了, 可以集中精力在功能设计和实现上了.

 

WinCE语音编/解码器优化
为了实现实时语音传输, 需要解决很多问题, 其中关键的是要实现高压缩的编解码器.
在可行性论证中, AMR-NB可以在GSMAMR_RATE_5150模式下, 把200多K的WAVE源语音, 压缩成只有5K大小的流, 并且失真很小(因为AMR是专门针对人声的算法, 对这个频段有很好的保真度).
而且在极低带宽下,还可以牺牲质量, 进一步提高压缩比.
AMR从技术上可以实现这个目标, 但是, 在ARM 100~200MHZ的核上, 编解码速度, 特别是编码速度, 也同样影响到实时性.
对于当时市场上还有INTEL的Intel的移动CPU : XSCAlE, 因此可以用IPP(INTEL 性能库来做). 不得不佩服INTEL的工程师, 采用INTEL指令集后, 处理速度为0.27倍实时, CPU占用也比较小, 比后来我在OMAP TI的核上(另一套AMR实现)优化后的速度还快了一倍!
对于OMAP TI的ARM核, 经过汇编优化后, 效率提高了35%, 加上对流的加密, 基本达到了0.7倍实时, 这样就基本满足了需求.

 

UGC 平台 : SNS 社交网站
07年, 随着六度分割理论在国内兴起, Ajax/Web2.0技术的普及, SNS(社交网络)概念也开始炒作起来, 当时还没有人人, 开心, 流行的只是论坛, 博客.
一开始, 管理层决定上线一个多人博客. 从此, 公司由软件到互联网的转型开始了.
首要目标是要设计公司设计UI, 板块. 还有就是要把前面实现的注册下载等既有的业务逻辑整合到新体系中去, 然后再新的CODE BASE上开发.

 

地图 : LBS / Lomoso的基础
前期工作完毕后, 产品部提了LBS(Location Based Service, 基于位置的服务) / LOMOSO(Location Specific Mobile Social Network, 基于位置的移动社交网络) 的需求概念(时值2006年底, 对于国内乃至整个互联网绝对是领先的领域), 开始了基于地理位置社交服务的设计和研究.
由于周围没有GIS相关的同事可以请教, 我只好啃书. 那时看了不少这方面的教材, 有了些投影制图, 坐标系等等的基础. 后来才发现, 其实事情可以很简单, 因为有现成的例子可以学 : Google maps
经过在浏览器动态Debug, 终于看到了google map与地图相关的计算流程, 但是这些JS是压缩过的, 写过JS的朋友应该知道, JS经过压缩(不准确的说法或俗称:加密), 一来可以让算法别人不容易看懂(全是a,b,c,d这样的变量名和函数名), 二来可以省掉不少存储空间.
于是我就反复跟踪, 结果发现, Wow, 这些函数似乎在做投影运算, 而这个投影很像教材里说的墨卡托投影(一种正轴等角切圆柱投影), 接下来又得到了由地图像素坐标到地理坐标的转换算法, 以及坐标到地图图块的计算算法, 至此, 我认为,其他剩下的都是力气活了. 但是, 一个意想不到的事情发生了: 真实的经纬度坐标和地图有误差, 而且是非线性的! (业界也没公开细节), 后来, 还是我隔壁的哥们得出的拟合法搞定了(人家是留洋的数学系硕士). 这几年以来, 我还在不时留意这个扰动算法如何解扰, 终于发现, 这个我国的又一伟大发明被称为"国家保密插件"或SM模组, 至于如何A掉它, 有兴趣的朋友可以先去逆下加扰算法^_^.

细心爱思考的人看到ditu.google.cn和maps.google.com的反应是什么?

它们相同吗? 有哪些不同? 为什么一开始google地图在中国境内就没有详细地图呢? 后来为什么又有了, 什么时候有的, 是不是有测绘公司合作了呢? 有了的图准确吗? 如何验证和衡量准确性? 有偏差吗, 有的话是什么偏差呢? 是有规律的吗? 能纠正吗? google从什么时候看到的中国地图变成高德(MapABC)提供的了? 它们的地图服务器体系是如何部署的? 又是从什么时候开始归并到google自己的地图服务体系中的? ditu.google代码中为什么有MapABC的计算程序? 为什么经历了几个版本后, 这些标识又消失了呢? 它们的程序架构每个版本都在更改, 他们的开发目标是什么? ......

每个技术细节背后都有可能隐藏很多有趣的故事, 尽管从表面看不出什么.

 

客户端 : LBS / Lomoso的表现
在网站上的表现, 可以用JAVASCRIPT(GOOGLE采用的主要手段), 也可以用FLASH(Yahoo采用的主要手段), 最终, 为了将来万一需要保持长连接和复杂绘图等等问题, 采用了FLASH作为WEB客户端的载体.
学习FLASH, 我又从零开始, 学习ACTION SCRIPT. 2个月后, 有了一个可以显示地图的版本, 而且支持标注, 移动, 缩放功能, 而且可以和卫星图来回切换(因为2者投影方式相同).
这在当时, 还是很新奇的, 而且完全实现了GOOGLE JS版 API的功能(Google MAPS Flash的API功能, 在这之后约1年后才发布).
接下来, 就是在地图层级上, 添加其他的POI, 也就是数据层, 类似Google earth, 上面很多种类星星点点的数据点, 有日志, 照片, 个人的位置等等. 以不同的图标表示, 用鼠标点击, 会弹出一个伸缩大小的气泡来显示具体信息和图片.
而且可以在一定时间后, 逐个弹出详情框,自动播放当前视图内的所有数据信息.
在登录后, 还可以显示好友位置, 按照设定的条件过滤当前视图的信息, 也可以选择一到多种感兴趣的数据类型来显示, 同时还支持翻页, 查看同一地区历史事件按照时间先后排序, 所有功能都开放, 提供给外部JavaScript调用......等等.

 

服务 : LBS / Lomoso的后端
在用Flash做模型的时候, 选取怎样的服务形式, 如何与服务器交互, 也是很棘手的问题.
我测试过很多模型, 包括最初的XML(效率最滥, 数据有效负载也低), JSON, NetString......
最后, 还是看了官方的AMF(Actionscript Message Format): 嗯, 二进制的, 靠谱. 这才走回正途.
数据流程是:DB->WebServer->Client, 加上国外牛人用C写的Module挂在PHP下, 效率比PHP软解AMF高不少.
基础设施搭建完毕, 开始数据库的设计, ER图, 既有数据结构, 要加上地理位置属性, 新业务, 要设计表. 根据查询, 业务模块等等优化, 聚合(离散)化数据结构(表结构).
逻辑和表现的分离, 数据库的优化, 整个服务构架的优化......

 

上线 : 产品/服务的发布
渐渐的, 所有的一切都从模型变成了真正可用的东西, 然后整理, 优化, 测试, 几轮下来, 稳定和性能都达到要求后, 就是整夜的产品上线过程.
大家都在各自的岗位上, 写产品上线的steps, 服务, 文件, 编译参数, 故障检测脚本, 一切都要万无一失按照顺序关闭, 启动, 调试.
当时我手里有6台server(后来有12台IBM x64 SERVER) , 按照次序PUTTY上去, 连命令都是先写到UltraEdit里, 标注好哪台SERVER执行哪条命令, 而且连万一出错该查那些文件, 日志路径都列出来.

 

系统性能分析 : 找出瓶颈, 负载极限, 改善构架
07年底, 产品做的差不多, 我一边改善, 维护所有做过的功能馍块, 一边handoff这些模块给其他人维护. 由于一直以来, 各个项目我都在写文档, 所以这方面只要给新人讲解如何使用基本就可以了.
在我们部门的几次会议后, 我工作重点就由开发转到了性能优化, 对象是整个服务系统.
性能优化, 是一个牵涉甚广的主题(软件和硬件), 而且和实际应用场景非常紧密.
这使我对操作系统, 文件系统, 数据库原理, 网络, 磁盘IO, 开始了比较深入的学习.
MySQL, Apache, PHP, XCache, memcache, lighttpd, nfs, squid, 从源代码的编译, 部署, 到参数配置都要很多试验, 测试. 有了测试数据, 然后才能有架构方案, 做到一切均用事实说话, 一切都由理论保证.

在通彻分析业务逻辑的基础上, 改善构架.
这其中细节和手段非常之多, 技巧也很多, 没法一一道来, 不过, 中心思想还是很明确的:
1.读写分离. 数据持久层(DB或自己实现的数据仓库)尽量减少读写资源竞争(update/insert和select, join查询), QPS(QUERY PER SECOND)每秒能处理的请求量是决定性参数.
2.动静分离. 动态和静态内容一定要分不同服务处理. PHP/ASP/JAVA动态产生的内容, 要有足够计算资源, 而其他仅占用磁盘IO的(CSS, HTML, 图片等), 统统用缓存或另外静态服务器处理.
3.Key-Value的思想无处不在(这也是后来NOSQL的核心).所有的问题本质就是KEY(request),服务以对应value的回复(reply).
4.根据缓存命中率来调整缓存对象的策略(过期时间......)
5.压缩前端内容.尽量减少页面大小.可以用Firebug等工具, 察看一次请求后, 页面加载每个元素的下载耗时, 找出瓶颈.

设计上, 也有核心思想
1.磁盘最慢, 尽量减少磁盘IO
2.能Cache的尽量cache(当然在保证有效Cache的前提下, 缓存命中率是依据)
3.分清计算型服务(对CPU要求高)和网络服务(对网络IO要求高)还是文件服务(对磁盘IO要求高), 合理安排, 组合.

目前SERVER的普遍配置是 : INTEL至强 + 64位Linux + 16G内存(越多越好) + Raid卡
除这些基本配置外, CPU缓存越大越好, 相同数量的物理核比逻辑核好很多, 内存越大越好, 硬盘一定要可靠, 而且, 硬盘速度是整个系统最大的瓶颈.

 

性能优化, 系统构架的终极目标 : Scalable
真正的水平扩展目标达成后, 优化, 构架就只剩配置, 上线新服务器的任务了.
当然, 这只是美好的愿望, 因为, 优化, 是伴随具体业务改变的, 是无止境的.

在第一家公司的前三年, 是技术积累最多的一个时期, 那些友好的同事给了我很多帮助, 特别是研发部老大, 他是我见过的技术最强的人:
1.从宏观上, 沟通产品部, 制定Roadmap, 把握项目周期, 里程碑, 技术难点以及解决问题的缓冲期, 从而可以帮助开发人员制定比较精确可信的schedule.
2.从微观上, 解决技术难题, 指明解决问题的方向, 如果开发人员实在无法搞定, 可以亲手指导. 算法, 构架, 研究方向, 都不是问题. 只要是C/C++, Linux/Win32/Symbian, 平台, 也不是问题.
3.从他身上, 可以体会到"懂" 与 "会"的区别.
"会"的人会告诉你如何去做, 如何去实现才能解决问题.
"懂"的人除了可以告诉你方法, 而且会告诉你问题是如何产生的, 其本质是什么, 可以有几种角度去解决, 如何最优, 还有没有其他相关或类似的问题, 如何处理此类一系列问题......等等, 非常系统.
我常常发现专业知识是如此有用, 深深感到我读的书实在太少, 很多人说的"读书无用论"是多么的可笑, 读书不是没有用, 而是那些人不懂如何运用, 用在什么地方.
(当然, 对于根本用不到专业知识的情况就另当别论了(纯粹的代码工), 或者"门槛岗位", 那种情况别说是"读书无用", 而是"上学无用". 混张文凭足矣)

 

而后, 由于想到外面看看, 于是就来到一家游戏公司.
09年初, 网络游戏很是流行, renren, kaixin, qq, 都在"争车位", "偷菜", 再又是"植物大战僵尸", 这些都是增加用户粘性的手段, 目的是留住用户在网站上的逗留时间, 继而想办法赚钱.

看着网络从"Web1.0"到"Web2.0", 再到后来的RIA(Rich Internet applications)富互联网应用程序, 大家似乎在把桌面的应用程序统统搬到Web上去, 从一开始的DIV拖动, 到后来Yahoo的YUI框架, 俨然一个Windows系统出现在一个页面里, 模态的, 非模态的对话框(而且是多个)
, 甚至根MDI程序一样, 窗口还有菜单和工具条.
还有jQuery, Ext框架, 比YUI易用小巧, 而且开放度很高, 有着大量插件, 可以满足几乎所有需求, 制造出非常酷的效果(渐隐, 飞入, 闪动 ... ), "富应用"的不得了.
一时间, 大家都在招兵买马, 一起"网络游戏"一把, 当时公司也不例外.
不过, 最终社区插件在我写了SPEC, 留了插件接口和设计后, 交给别人去做了.
我转而去对H264视频编解码研究了一番. 后来写了个视频COM组件, 可以在游戏大厅多人棋牌中视频.
用的是UDP, 服务端担当P2P服务器的角色来完成NAT Punch-through的过程,并且管理所有Session.
客户端可以穿NAT, 但也不是100%的, 因为依赖具体网络环境(路由策略), 通讯虽然是UDP的, 有丢包的可能, 但是可以调整UDT(UDP可靠传输)的参数,  丢包的情况可以分级别控制, 甚至到最大级别, 就是个完全可靠的TCP, 只不过是用UDP实现的TCP算法.
熟悉这方面技术的朋友应该可以联想到, 这方面公认的技术的基础项目有UDT和RakNet.

 

CMMI5 : 软件工程 + 管理
如果想亲身体会软件开发中比较正规的流程, 可以到专业软件外包公司看看.
我想搞清楚专业的软件工程在现实中如何体现, 正巧有个CMMI5在招Senior Unix Consultant, 于是就去了.
在SingTel Group下的这家外包公司规模大(苏州公司有700多人), 正规, 业务遍及全球, 项目历史也很长.
我所在的项目组负责的是某知名全球银行的综合支付系统, 项目历史可以追溯到1995年,平台是HP-UNIX和IBM-AIX, 开发是C和Sybase PowerBuilder.
系统是按照Unix思维方式搭建的, 业务逻辑放在了数据库的存储过程中,所以,所有的工作介质就是C/SP/PB.
有很严格的Policy(严格防止资料的泄漏), 个人电脑的权限也是经过限制的, 就是说, 私自安装软件/使用USB, 光驱等等是不被允许的, 虽然对个人来说少了些自由, 但这正好说明了管理的正规和严密, 有一定规避风险的机制, 我还是挺赞同的.
说到工作, 在团队里, 氛围不错, 大家都是一起干活的XDJM, 互相照应.
平时大家工作上都是和新加坡总部MAIL联系, 这就要注意下"Mail文化" : 知情的范围要恰当, 想澄清的一定要写清楚, 重要的KEY POINT要留底以备查证.
对客户要有专业精神 : 回信及时, Title, 措辞, Signature要正规, 最忌拼写/语法错误.

所有的工作阶段, 从需求分析, 概要设计, 实现设计, 编码, 编译, 单元测试, 系统整合测试, 全要code review代码审核, 审核负责人要签名, 所有测试数据, 文档, 全要留底和代码一起提交, 最终由专人负责冻结代码,再在生产环境副本的测试环境做测试(cutover), 通过后入库check in,等待正式上线(product online)
每个阶段/各种文档和代码一起, 作为一个Work Request(一次工作单位). 所有这些WR, 都有个唯一ID, 以表示这个项目历史中曾经发生过一次修改. 然后在积累了一定WRs后(按照用户的要求), 准备上product, 决定本次promote哪些WRs, 然后产生check list, 按步骤编译c, pb, fire sp到DB等等, 按部就班.
所有人在这个过程中要同步配合, 昼夜职守, 万一不成功就回滚, 查原因, 再promote, 直到成功为止, 不成功则成仁! 面对银行客户, 一定要在上班前搞定一切, 并且确保正常运转.
而且面对多个国家, 逻辑不尽相同, 有时要针对不同国家准备多个版本, 非常细心才行.
有了前面的严密的工作, 基本到后来没多大问题的, 大多数delay是数据或环境造成的, 不过仅仅这些外界的不同, 就足以让人忙上半天了.
但是, 这些维护是一直进行下去的, 因为客户外包项目给公司, 不是交付使用后就了事的, 项目会一直继续下去, 新需求不断, 维护也很多, 真正的把项目"外包"给专业开发公司去做, 而非一般外包公司, 一个项目做完, 基本就完事了, 然后再接新项目.

 

一切动力的源头 : 兴趣和好奇心
"系统是如何运作的? 为什么被设计成这样? 如何做才能使它更高效稳定?", 带着心中这些疑问, 我去学习和实践每个问题.
对于知识的积累来说, 只要有兴趣, 有好奇心, 就自然有动力, 有持久性, 最终一定可以有所作为.
为了达到"了解"这个目的, 我在第一家公司早八点晚八点, 加上周末, 除了吃饭睡觉, 就是读书思考, 抽象模型, 写代码. 不知不觉持续近两年.
再加上紧接着一年半的性能分析, 一路走来, 平台从PC到WinCE, Linux.工作范围从网络客户端, 网络服务, 再到Web开发, 构架, 性能优化. 这些解决了过去我心中的很多疑惑.

 

编程的本质 : 数学和哲学
算法和数据结构是数学的计算机描述, 而程序体系, 架构, 源自于逻辑, 方法论, 归根到底就是哲学. 这就是为什么有数学功底的人很适合写程序, 而且写的程序高效, 能解决一般人无从下手的问题.
其他的, 像不同的平台, 驱动程序, MFC, API, C库函数, STL, 多线程, 多进程, 封装COM组件, DLL库等等, 全部都是"招式", 而非"内功". "招式"可以速成, 而"内功"不可以, 这就是二者最大的差别.
环顾专业书籍, "招式"何其多! 招式是重要, 但由于不是"本质"的东西, 因此可以把人教"会", 让人会干活, 但没教"懂", 更别提创新了.

有人谈到C, "高效", "简洁", "对OO支持不好", "难以模块化", 谈到C++, "带类的C", "效率没有C好, 但比JAVA快, 因为JAVA是跑在虚拟机上的"......(听后让人想自杀)
有人谈到多线程, 动不动就"再开一个线程", "线程多点效率当然高", 出了问题第一反应是"好像哪里不对了, 貌似是同步问题, 加锁后试一下", "临界区不行, 不能跨进程, 不如用Mutex, 信号量", "实在不行, 写个RW读写锁"......(听后让人觉得碰到高手了)
有人整天满口的:"线程池", "连接池", "缓冲", "内存池", "垃圾回收", "同步问题", "加锁", "队列", "自旋锁", "原子操作"......(听后让人觉得遇到专家了)
但是这些人中, 很多都是"眼高手低" : 这些的确是编程的利器, 但却并没能解决他们的问题, 往往结果不随人愿:"啊?!怎么会这样? 可能是其他什么地方不对, 我再改改看......"(已经开始疑神疑鬼, 不唯物主义了)
没有算法和数据结构, 一切都是空淡. 玩技术的越到后来越有体会.
这点不是三言两语能表达出来的, 知者自知.

 

不论走多远, 都不要忘记出发时的目标
有了这些比较系统的学习, 才有了实现自己想法的基础.
随后这两年以来, 对于一些想法, 不管有多久远(甚至包括大学时的一些想法), 我都打算亲手实现它们. 因为, "不论走多远, 都不要忘记出发时的目标".
为了完成这些目标, 不管还有多少路要走, 都永不放弃.

TruthTracer (01/05/11 mm/dd/yy)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值