多线程程序设计中的8条简单原则

规则1:找出真正独立的运算

规则2:在尽可能高的层次上实现并发

规则3:尽早考虑通过增加处理器核的数量来获得可伸缩性

规则4:尽可能使用线程安全的库

规则5:使用正确的多线程模型

规则6:永远不要假设程序会按照某种特定的顺序执行

规则7:尽可能使用线程局部存储或者与特定数据相关的锁

规则8:要敢于对代码进行修改以获得更好的并发性

仔细看了一下这八个条目的具体内容,发现确实只是字面意思。现在并发软件技术还算发达,目前主流的处理器是8核或者更多,作者写上面八个原则的时候,主流处理器的核心是四核,由于历史遗留问题往往很少考虑并行计算,而多核服务器就这么被暴殄天物了,哈哈哈。

目前对于我来说,redis+线程池+队列+锁,就可以解决目前工作场景的所有需求,甚至只要一个队列,就连锁都不要,其实我并没有合理发挥出线程的优势,其实线程的优势是线程间通信,比起进程间通信会优雅很多。pthread.h的参考文档https://pubs.opengroup.org/onlinepubs/009695299/basedefs/pthread.h.html,对于pthread是内核级还是用户级线程的解释如下:


这个事情,还真不是一句话就能回答的,因为涉及到Linux和编译器的版本

关于线程的概念不多说了,内核级和用户级线程的定义网上也有,简单的说:内核级就是操作系统内核支持,用户级就是函数库实现(也就是说,不管你操作系统是不是支持线程的,我都可以在你上面用多线程编程)。

好了,那么,我们首先明白一件事:不管Linux还是什么OS,都可以多线程编程的,怎么多线程编程呢?程序员要创建一个线程,当然需要使用xxx函数,这个函数如果是操作系统本身就提供的系统函数,当然没问题,操作系统创建的线程,自然是内核级的了。

如果操作系统没有提供“创建线程”的函数(比如Linux 2.4及以前的版本,因为Linux刚诞生那时候,还没有“线程”的概念,能处理多“进程”就不错了),当然你程序员也没办法在操作系统上创建线程。所以,Linux 2.4内核中不知道什么是“线程”,只有一个“task_struct”的数据结构,就是进程。那么,后来随着科学技术的发展,大家提出线程的概念,而且,线程有时候的确是个好东西,于是,我们希望Linux能加入“多线程”编程。

要修改一个操作系统,那是很复杂的事情,特别是当操作系统越来越庞大的时候。怎么才能让Linux支持“多线程”呢?

首先,最简单的,就是不去动操作系统的“内核”,而是写一个函数库来“模拟”线程。也就是说,我用C写一个函数,比如 create_thread,这个函数最终在Linux的内核里还是去调用了创建“进程”的函数去创建了一个进程(因为OS没变嘛,没有线程这个东西)。 如果有人要多线程编程,那么你就调用 这个create_thread 去创建线程吧,好了,这个线程,就是用库函数创建的线程,就是所谓的“用户级线程”了。等等,这是神马意思?赤裸裸的欺骗?也不是。

为什么不是?因为别人给你提供了这个线程函数,你创建了“线程”,那么,你的线程(虽然本质上还是进程)就有了“线程”的一些“特征”,比如可以共享变量啊什么的,咦?那怎么做到的?当然有一套机制,反正人家给你做好了,你用就行了。

这种欺骗自然是不“完美”的,有线程的“一些”特征,但不能完全符合理论上的“线程”的概念(POSIX的要求),比如,这种多线程不能被分配到多核上,用户创建的N个线程,对于着内核里面其实就一个“进程”,导致调度啊,管理啊麻烦.....

为什么要采用这种“模拟”的方式呢?改内核不是一天两天的事情,先将就用着吧。内核慢慢来改。

怎么干改内核这个艰苦卓越的工作?Linux是开源、免费的,谁愿意来干这个活?有两家公司参与了对LinuxThreads的改进(向他们致敬):IBM启动的NGTP(Next Generation POSIX Threads)项目,以及红帽Redhat公司的NPTL(Native POSIX Thread Library),IBM那个项目,在2003年因为种种原因放弃了,大家都转到NPTL这个项目来了。

最终,当然是成功了,在Linux 2.6的内核版本中,这个NPTL项目怎么做的呢?并不是在Linux内核中加了一个“线程”,仍然和原来一样,进程(其实,进程线程就是个概念,对于计算机,只要能高效的实现这个概念就行,程序员能用就OK,管它究竟怎么实现的),不过,用的clone实现的轻量级进程,内核又增加了若干机制来保证线程的表现和POSIX相同,最关键的一点,用户调用pthread库创建的一个线程,会在内核创建一个“线程”,这就是所谓的1:1模型。所以,Linux下,是有“内核级”线程的,网上很多说Linux是用户级线程,都是不完整的,说的Linux很早以前的版本(现在Linux已经是4.X的版本了)。

还有个 pthread 的问题,pthread是个线程函数库,他提供了一些函数,让程序员可以用它来创建,使用线程。那么问题是,这个函数库里面的函数,比如 pthread_create 创建线程的函数,他是怎么实现的呢?他如果是用以前的方法,那程序员用它来创建的线程,还是“用户级”线程;如果它使用了NPTL方式创建线程,那么,它创建的线程,就是“内核级”线程。

OK,结论,如果你 1:使用2.6的内核的系统平台,2:你的gcc支持NPTL (现在一般都支持),那么你编译出来的多线程程序,就是“内核级”线程了。

所以,现在回答问题,只要你不是很古董级的电脑,Linux下用pthread创建的线程是“内核级线程”

最后,这NPTL也并不是完美的,还有一些小问题,像有一些商业操作系统,可以实现混合模型,如1:1,N:M等(就是内核线程和用户线程的对应关系),这就强大了,Linux仍有改进的空间

下面是常见编程思想:

编程范型编程范式程序设计法(英语:Programming paradigm),(即模范、典范之意,范式即模式、方法),是一类典型的编程风格,是指从事软件工程的一类典型的风格(可以对照方法学)。如:函数式编程、过程式编程、面向对象编程、指令式编程等等为不同的编程范型。

编程范型提供了(同时决定了)程序员对程序执行的看法。例如,在面向对象编程中,程序员认为程序是一系列相互作用的对象,而在函数式编程中一个程序会被看作是一个无状态的函数计算的序列。

正如软件工程中不同的群体会提倡不同的“方法学”一样,不同的编程语言也会提倡不同的“编程范型”。一些语言是专门为某个特定的范型设计的(如Smalltalk和Java支持面向对象编程,而Haskell和Scheme则支持函数式编程),同时还有另一些语言支持多种范型(如Ruby、Common Lisp、Python、Rust和Oz)。

很多编程范型已经被熟知他们禁止使用哪些技术,同时允许使用哪些。例如,纯粹的函数式编程不允许有副作用[1];结构化编程不允许使用goto。可能是因为这个原因,新的范型常常被那些习惯于较早的风格的人认为是教条主义或过分严格。然而,这样避免某些技术反而更加证明了关于程序正确性——或仅仅是理解它的行为——的法则,而不用限制程序语言的一般性。

编程范型和编程语言之间的关系可能十分复杂,由于一个编程语言可以支持多种范型。例如,C++设计时,支持过程化编程、面向对象编程以及泛型编程。然而,设计师和程序员们要考虑如何使用这些范型元素来构建一个程序。一个人可以用C++写出一个完全过程化的程序,另一个人也可以用C++写出一个纯粹的面向对象程序,甚至还有人可以写出杂揉了两种范型的程序。

  • 结构化编程对比非结构化编程,大部分高端程序语言都期望用户进行结构化编程
  • 命令式编程对比宣告式编程
  • 消息传递编程对比命令式编程
  • 步骤式编程对比函数式编程,后者的著名例子是Haskell
  • Value-level programming对比Function-level programming
  • 流程驱动编程对比事件驱动编程
  • 纯量编程对比阵列编程,后者的例子包括 R语言 、 MATLAB 及 Perl Data Language 等
  • 基于类编程对比基于原型的编程(面向对象编程的流派)
  • 规则式编程及以其为基础的约束逻辑编程(逻辑编程的流派)例子: Prolog
  • 基于组件编程例子:OLE
  • 面向方面编程例子:AspectJ
  • 符号式编程例子:Mathematica、Maxima
  • 面向表格编程例子:Microsoft FoxPro
  • 管道编程例子:Unix命令中的管道
  • Post-object programming
  • 面向主题编程
  • 自省编程(或称反射编程)
原文地址:https://www.cnblogs.com/still-smile/p/13624527.html