java的多线程机制

在项目中,经常会使用到多线程,例如android本身封装了handler来进行多线程通信,平时会用到eventbus,rx这样的框架来处理,自己用锁的时候已经很少了,但还是无法完全避免。多线程的概念非常好理解,是为了提高工作效率的一种方法,尤其在现代多cpu多核的计算机下,利用好各个资源是非常有必要的。在android等交互上,为了给用户良好体验,不能阻塞用户交互请求也必须在非ui线程上更新ui。

线程之间如何正确的通信是我们所关注的最关键的点。

首先问题在于线程为什么存在同步和通信的问题,这个可以看些java线程内存模型的文章,简单来说原因在于,jvm为每个线程维护了一个私有内存,线程间是不能直接通信的,他们通过与主存通信完成同步。大家知道,所谓线程,其实就是运行在cpu的指令流,就是方法的顺序执行。比如说,方法 f(),在线程1上被调用的,则这个方法是在线程1上执行的,咋一看像句废话,其实很多人会陷入某个变量是哪个线程的,比如说handler的理解上,经常有说是哪个线程的handler,实际上只是他们的loop方法在那个线程调用了而已,那只是一种易于记忆的说法,希望大家仔细思考。这里也同样说明了另外一个问题,即局部变量是不存在线程同步问题的,因为它的生命周期就是一个方法,即一个局部变量对象只存在于一个线程上。而相应的全局变量是存在线程安全问题的。每个线程内存维护了一份该变量的拷贝,或者说clone更便于理解,拿mips作为模型举例来理解,就是比如全局变量A a;会有一个寄存器存储其的地址,对应地址的内存上存有A的信息,成员变量值什么的,每个线程用到时都会从主存拷贝一份以上的信息。但是并不是立刻同步的,想要立刻写回可用volatile修饰。(非常不建议的做法)

这里,比如A里的成员变量 int mTv = 1;在线程1上做了mTv++运算,变成2,这时还未写回,但是线程2又做了一遍,则出现了同步问题,与我们预期是不一样的。这就是我们所要注意和需要解决的问题。

多线程不是java特有的,甚至java是没有自己的线程模型的,而是直接采用了操作系统的线程模型。很多维护机制都是从操作系统来的。下面介绍一下大家最常见到的volatile,(就是大家经常觉得反正加了保险的那个),这里已经无数工程师劝过,这个要尽量避免使用,因为至今其使用场景都是非常之低的,反而会带来一些其他的问题。那么它到底什么意思呢。volatile修饰变量,有强制从主存读和回写的作用,理解起来很简单,就是用的时候从主存读,改变了就往主存回写。请注意,它完全不能解决我们的多线程问题!!这里就不得不提到另一个人气更高的关键字:synchronized,这也是jdk5唯一实现锁的方式(也就是说volatile根本不能算锁),理解更加简单,比如举个例子,被其修饰的变量是不会被两个线程同时调用改变的,是真真正正的锁,当然这是最重的锁了,大家想一下就知道这种方式是非常保险的,但也是非常不高效的(就是那个最笨的方法)。synchronized可以保证操作是原子性的,volatile是不能保证的。

什么叫原子性呢,大家知道物理学原子某种程度上算是物体组成基本物质了,可以理解为不可分割的,这里只是便于大家理解关键字概念,不涉及物理学知识。强制读写就不是一个原子性操作,比如i++,看起来是一步,实际上,要从主存读,然后把值拷贝给临时变量,临时变量加一赋回i,然后写回主存,也就是说,这整个是可以分割的,是可以进行一半暂停的,这里我们完成了加法运算还没写回主存,另一个线程调用i,从主存读值,显然出现了同步问题。线程工作内存可以说是主存的一份缓存,为了避免缓存不一致,volatile需要废掉此缓存。除了内存缓存之外,在CPU硬件级别也是有缓存的,即寄存器。假如线程A将变量X由0修改为1的时候,CPU是在其缓存内操作,没有及时回写到内存,那么JVM是无法X=1是能及时被之后执行的线程B看到的,JVM在处理volatile变量的时候,也同样用了硬件级别的缓存一致性原则。详细请查阅硬件级别cpu缓存相关的博客。

volatile是可以防止指令重排的,我觉得这个没什么特别大意义,大家感兴趣可以自己了解一下,其实就是汇编里那个流水线,可以算是cpu对代码运行的优化,总之建议大家不要随意使用。使用可以参阅正确使用 Volatile 变量

synchronized这个用法,从对方法的修饰上来讲,其实可以理解为对对象的修饰,即是每个普通方法加了一个锁,这个锁便是对象本身。所以直接以synchronized (a){}为例,这里是给代码块上了一把对象a的锁。锁在Java内存模型里在不同机制下对应不同的数据结构。每个对象都有个长度2个字宽的对象头(在32位虚拟机里,1字宽是4个字节,64位虚拟机里,1字宽是8个字节。如果是数组对象,则对象头是3个字宽,其中第三个字存储数组的长度),这里面存储了对象的hashcode或锁信息,官方称它为“Mark Word”,如下图:

对象头的最后两位存储了锁的标志位,01是初始状态,未加锁,其对象头里存储的是对象本身的哈希码,随着锁级别的不同,对象头里存储不同的内容。偏向锁存储的是当前占用此对象的线程ID;而轻量级则存储指向线程栈中锁记录的指针。以上参考Java的多线程机制系列:(三)synchronized的同步原理。一把锁被一个线程持有,走完锁住得代码快锁会被自动释放,这里也可以在运行一半调用a.wait()方法释放锁,阻塞当前线程。另一个线程执行到某段代码后希望刚才那个线程继续运行,则可以调用a.notify()。当等待在obj上线程收到obj.notify()时,它就能重新获得obj的独占锁,并继续运行。注意了,notify()方法是随机唤起等待在当前对象的某一个线程。

以上可以作为多线程入门的参考,有时间写一下高级并发包的使用。

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

推荐阅读更多精彩内容

  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,230评论 11 349
  • Java8张图 11、字符串不变性 12、equals()方法、hashCode()方法的区别 13、...
    Miley_MOJIE阅读 3,698评论 0 11
  • Java-Review-Note——4.多线程 标签: JavaStudy PS:本来是分开三篇的,后来想想还是整...
    coder_pig阅读 1,643评论 2 17
  • 亲爱的邹小北小姐, 你好,初次见面,内心忐忑 ,久候多时,终尝所愿! 现在是公历2016年2月20日,东二区时间下...
    野雾啦吠放阅读 1,730评论 4 15
  • 宇宙的神秘之处应该在于它的深不可测与韵味无穷 地球存在于太阳系中 太阳系有八大行星 太阳系又存在于银河系中 银河系...
    杨安生姑娘阅读 476评论 0 2