并发编程笔记(1)

并发编程

最近在学习即刻时间王宝令老师的并发编程专栏,有一种醍醐灌顶的感觉。故对前四篇文章做个总结。

如何设计一个并发程序?

把并发编程抽象一层,你会发现当你写一个并发程序的时候,干的就是三件事:

分工:考虑的事把一个任务拆解成多少个子任务分别分配给多少个线程做呢,比如说采用并发的方式实现wordcount,那么我可能能把这个任务拆解成 1.对文件进行切割 2.对这些不同的切割分别计算它们的所包含的词的数量 3.把最后的结果输出出来。
而这三类任务,1和3在主线程中做,2就由多个线程进行并行执行。

协作: 考虑的是任务启动的时机,最主要的就是任务之间的依赖关系,如同一个DAG一般,一个线程执行完了一个任务,要通知哪些后续的任务的线程开工。而对于上面的例子而言,主线程一边做着1任务,切割了一个就启动一个线程干2任务,然后等所有的2任务干完了,主线程就可以干三任务。

线程安全(互斥):分工同步考虑了程序的性能,但并发程序中准确性问题同样至关重要。从任务具体执行的角度上看,任务之间同样可能不是说能够独立运行,因为他们可能共享着变量,可能会有变量的可见性,原子性,顺序性的问题。接着上面的例子,我们在任务2中用了一个共享变量count计算词的总数,由于多个线程对count进行操作,所以可能就需要对这个count采用原子的方式进行修改,比如用锁,用CAS等等。

并发编程.png

(我其实觉得协作互斥的名字起得不是很好,但我也没有想到能够简单表达意思的好名字,😔。)

并发编程的问题根源是啥子?

计算机在飞速发展,但核心矛盾仍然是CPU,内存,磁盘的性能差距,形象点说,CPU 是天上一天,内存是地上一年;而如果内存是天上一天,I/O 设备是地上十年。于实乎就有什么L1 L2等告诉缓存去均衡CPU与内存的速度差距;就有对进程,线程对CPU进行分时复用,均衡CPU与I/O设备的差距;编译程序优化指令执行次序,使得缓存能够得到更加合理地利用。而这三方面的改进,同时也引入了三方面的问题,缓存的存在,数据的修改如何让其他线程看见,可见性问题;比如一个I++的操作,多个线程运行,线程切换的时候,就可能导致这个i++操作停i变量的加载过程中,从而导致原子性问题。指令顺序的重排,导致其他线程不能以该线程的代码顺序做假定编写代码。比如下面事例,线程二就不能因为线程一中i=10 是在isOutPut = true之前的,所以就认为输出的i一定是10。


//线程一
i = 10
isOutput = true;

//线程二
if(isOutput){
    System.out.println(i);
}

java内存模型,能不能讲的对程序员友好点?

什么java内存模型,尤其是happens-before规则,一直以来我就感觉要么是废话,要么不知道肿么用。王宝令老师给了一个特别对广大程序员友好的解释。因为缓存导致了可见性问题,因为指令重排导致了顺序性问题,那么我们是不是可以通过按需禁止缓存,按需禁止指令重排解决进行解决呢。而java内存模型正是规范了按需禁止缓存指令重排的方法。这些方法包括 volatile、synchronized 和final 以及happenbefore的六项规则。

happenbefore 影响的是顺序性,和可见性语义

  1. 在同一个线程中,前面的操作happens-before于后面操作。这个规则其实很显然,但需要强调的是这并不是说禁止指令重排。在i=10的后面,你都可以利用i=10这个信息,但如果你没用,是不是说我放到j=10后面执行也ok呢。
i=10;
j=10;
  1. volatile 变量规则 , 对volatile变量的写操作 happens-before 对volatile变量的读操作。这条规则好像和禁用缓存的效果是一致的, 所以对这条规则我一直有个问题,就是首先这条规则无疑是针对一个线程写,另外的线程读的场景的,那么我在写线程二的程序的时候,同样还是有顺序性问题呀?

//线程一
i = 10 //操作1
volatile isOutput = true;//操作2

//线程二
if(isOutput){//操作3
    System.out.println(i);//操作4
}

然而我忽略了

  1. 传递性规则如果 A Happens-Before B,且 B Happens-Before C,那么 A Happens-Before C。

有什么用呢? 如果线程二if isOutput 为true了,那由规则2 操作2 happens-before 操作3,由规则一 操作3 happens-before 操作4,所以操作2 happens-before 操作4,同理可证 操作1happens-before 操作4。 简直棒呆。所以1,2,3规则结合起来用,也就说明了volatile修饰变量的禁用缓存,禁用指令重排的语义。

  1. 管程中的锁规则
    对一个锁的解锁 Happens-Before 于后续对这个锁的加锁操作。

  2. 线程start() 规则
    它是指主线程 A 启动子线程 B 后,子线程 B 能够看到主线程在启动子线程 B 前的操作。

  3. 线程join()规则
    主线程A等待子线程B运行完后,主线程A能够看到子线程B的操作。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345