有没有一些轻量级的方案来实现多线程安全的访问数据呢?这个时候,你需要:
无锁编程技术
多线程并发编程中,遇到公共数据时就需要进行线程同步 。而这里的同步又可以分为阻塞型同步和非阻塞型同步 。
阻塞型同步好理解,我们常用的互斥体、信号、条件变量等这些操作系统提供的机制都属于阻塞型同步,其本质都是要加“锁” 。
文章插图
与之对应的非阻塞型同步就是在无锁的情况下实现同步,目前有三类技术方案:
- Wait-free
- Lock-free
- Obstruction-free
Lock-free能够广泛应用得益于目前主流的CPU都提供了原子级别的read-modify-write原语,这就是著名的CAS(Compare-And-Swap)操作 。在Intel x86系列处理器上,就是cmpxchg系列指令 。
// 通过CAS操作实现Lock-free do {... } while(!CAS(ptr,old_data,new_data ))
我们常常见到的无锁队列、无锁链表、无锁HashMap等数据结构,其无锁的核心大都来源于此 。在日常开发中,恰当的运用无锁化编程技术,可以有效地降低多线程阻塞和切换带来的额外开销,提升性能 。服务器上线了一段时间,发现服务经常崩溃异常,排查发现是工作线程代码bug,一崩溃整个服务都不可用了 。于是你决定把工作线程和主线程拆开到不同的进程中,工作线程崩溃不能影响整体的服务 。这个时候出现了多进程,你需要:
进程间通信技术
提起进程间通信,你能想到的是什么?
- 管道
- 命名管道
- socket
- 消息队列
- 信号
- 信号量
- 共享内存
对于本地进程间需要高频次的大量数据交互,首推共享内存这种方案 。
现代操作系统普遍采用了基于虚拟内存的管理方案,在这种内存管理方式之下,各个进程之间进行了强制隔离 。程序代码中使用的内存地址均是一个虚拟地址,由操作系统的内存管理算法提前分配映射到对应的物理内存页面,CPU在执行代码指令时,对访问到的内存地址再进行实时的转换翻译 。
文章插图
从上图可以看出,不同进程之中,虽然是同一个内存地址,最终在操作系统和CPU的配合下,实际存储数据的内存页面却是不同的 。
而共享内存这种进程间通信方案的核心在于:如果让同一个物理内存页面映射到两个进程地址空间中,双方不是就可以直接读写,而无需拷贝了吗?
文章插图
当然,共享内存只是最终的数据传输载体,双方要实现通信还得借助信号、信号量等其他通知机制 。
用上了高性能的共享内存通信机制,多个服务进程之间就可以愉快的工作了,即便有工作进程出现Crash,整个服务也不至于瘫痪 。
不久,老板增加需求了,不再满足于只能提供静态网页浏览了,需要能够实现动态交互 。这一次老板还算良心,给你加了一台硬件服务器 。
于是你用JAVA/php/Python等语言搞了一套web开发框架,单独起了一个服务,用来提供动态网页支持,和原来等静态内容服务器配合工作 。
这个时候你发现,静态服务和动态服务之间经常需要通信 。
一开始你用基于HTTP的RESTful接口在服务器之间通信,后来发现用JSON格式传输数据效率低下,你需要更高效的通信方案 。
这个时候你需要:
RPC && 序列化技术
什么是RPC技术?
RPC全称Remote Procedure Call,远程过程调用 。我们平时编程中,随时都在调用函数,这些函数基本上都位于本地,也就是当前进程某一个位置的代码块 。但如果要调用的函数不在本地,而在网络上的某个服务器上呢?这就是远程过程调用的来源 。
文章插图
从图中可以看出,通过网络进行功能调用,涉及参数的打包解包、网络的传输、结果的打包解包等工作 。而其中对数据进行打包和解包就需要依赖序列化技术来完成 。
什么是序列化技术?
推荐阅读
- 春季忽冷忽热易引疾病 胃肠疾病复发危害大
- 唐宣宗与唐武宗 唐高宗时期的大臣
- 黑骨茶和小叶紫檀区别,浅析大叶种茶和小叶种茶之间有哪些区分
- 静下心来品杯茶,静下心来
- 喝茶有十大误区,十大养生壶品牌有哪些
- 喝青茶能减肥吗,大麦茶能天天喝吗
- 于谦的经历 于谦的骨血
- 公孙瓒手下的大将和谋士 公孙瓒手下大将
- 十大海南美食推荐
- 洪荒十大圣人排名是怎样的?