Java多线程之原子性

友情提示:作为一个java小白最近在看java多线程知识,东西还是比较多,推荐大家去看《Java多线程编程指南》,怕自己忘了,所以决定码些字。

开始之前,建议大家一定要系统地学习一下操作系统,并且不能光看网上碎片化的知识点,所以一点一点来吧。

我准备先回顾一下非常基础而且重要的知识点,先从三个特性下手,原子性,可见性,有序性。每一点的内容都很多,一点一点来,先介绍原子性。

原子性:

书本上的定义:对于涉及共享变量访问的操作,若该操作从其执行线程以外的任意线程来看是不可分割的,那么该操作就是原子操作,相应的我们就称该操作是具有原子性的。

这句话的丰富含义有:

1.原子操作是对于多线程而言的,对于单一线程,无所谓原子性。有点多线程常识的朋友这个都应该知道,但也要时刻牢记。

2.原子操作是针对共享变量的。因此,涉及局部变量(如方法中的变量)我们是没必要要求它具有原子性的,

3.原子操作是不可分割的。(我们要站在多线程的角度)指访问某个共享变量的操作从其执行线程之外的线程来看,该操作要么已经执行完毕,要么尚未发生,其他线程不会看到执行操作的中间结果。学过数据库的朋友应该很熟悉这种原子性。那么,站在访问变量的角度,我们可以这样看,如果要改变一个对象,而该对象包含一组需要同时改变的共享变量,那么,在一个线程开始改变一个变量之后,在其它线程看来,这个对象的所有属性要么都被修改,要么都没有被修改,不会看到部分修改的中间结果。(这只是最简单的一种解释,以后我们还会讲到i++以及初始化等操作)

好了,这是我们从书上定义角度出发得到没有任何问题的定义,下面我想说说我对原子性的理解(可能有误,欢迎指正)。

首先保持原子性的重要性不言而喻,这可能是我们学多线程最直观的感受。我们需要让一个共享变量串行的被访问修改,不能造成不一致性。

这里先说一下互斥性,学过操作系统的同学课上可能都接触过生产者消费者模型,这个模型里面的共享变量就是缓存区的大小。我们学过通过一个互斥变量+临界区来控制两个线程对缓存区的访问实现方式大概是:

```

int mutex = 1;

while(true){

    wait(mutex);

    critical section

    signal(mutex);

}

```

上面的这个伪代码大概就是实现互斥访问的机理,wait(mutex)操作相当于:

```

while(mutex <= 0);

mutex--;

```

wait()操作的意思就是当互斥变量mutex<=0时,就一直阻塞在这里(不停循环)。若mutex>0,其实就是等于1,那么将mutex值变为0,接着执行临界区代码。这就保证其他线程此时想进入临界区时由于得到mutex为0,就一直阻塞。那么我们肯定还要想办法把mutex变回1,不然之后线程就进入不了临界区了。所以,大家就很容易想到signal(mutex)做的事情了:mutex++;

这里需要注意的是,我们要与多线程里面的wait(),signal()/notify()区别一下。上面讲的互斥变量其实就是的原理。同一时间我们只有一个线程能拥有锁,所以锁具有的排他性。那么,实现锁基本有两种方法:

1.synchronized(内部锁)/Lock(显示锁)。

2.CAS(Compare And Swap),这其实是锁的底层实现。之后再细讲这两块。

说的有点多,拉回来。通过互斥变量(锁)的特性,我们可以实现多个线程执行代码到这个区域的时候必须先获得许可,而且同一时间只有一个线程可以做到,所以咱们就实现了串行化。

OK,到这里我们实现原子性就很简单了,只需要把对一组共享变量的操作(或者对一个共享变量的多个原子操作)放进临界区就可以了。这样,在执行线程以外的其他线程看来,临界区不管有多少操作都是原子操作。

当然了,在Java里面要实现这种多线程并发访问这远远不够的。

我还要强调一个很重要的东西,如何判断一个操作是不是原子操作呢?

记住,在Java语言中,long型和double型以外的任何类型的变量的写操作都是原子操作。(不提读操作的原因是如果所有线程都是读操作的话,那么没必要保持原子性。我们需要考虑的是read-modify-write和check-then-act这两种形式)

所以对于基本类型和引用类型的写操作(不是指初始化)都是本身具有原子性的。对于long型和double型我们可以简单理解在32位虚拟机上,我们先对变量的低32位赋值,再对高32位赋值,那么这样两个操作就不是原子操作了,我们很可能读到中间状态。处理这种变量我们可以加一个volatile关键字,之后的文章我会详述这个关键字。

还有一个命题:原子操作 + 原子操作 != 原子操作

这里给大家一个很简单的判别方式,也就是我们赋值语句=的右边,(前提是=左边是对共享变量的操作)一旦出现共享变量了,那么就不是原子操作了,因为这肯定涉及读操作和写操作。最容易理解的就是i++(i=i+1)。

最后,要更好得理解原子性,我们最好去理解一下java内存模型,以及读写操作的过程。这一块很重要,大家不要忽略。

写的第一篇文章,有问题欢迎指正,下一篇给大家介绍 可见性。

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

推荐阅读更多精彩内容