1、引入问题
最近一直在看多线程这块知识,但是在看到关于“原子操作”网上的一些文章的时候感觉有些地方不对,下面有些地方提出了自己的想法,有什么不对的地方还请大家指正。
先看下面这两个问题,第一个问题是貌似是一个百度的笔试题,网上有不少文章做了分析,第二个只是我自己衍生了下:
以下多线程对int型变量x的操作,哪几个不需要进行同步
A. x=y; B. x++; C. ++x; D. x=1;
以下多线程对long型变量x的操作,哪几个不需要进行同步
A. x=y; B. x++; C. ++x; D. x=1;
对于第一道题,网上给的答案都是D,这个我个人持有异议(因为D只是一个原子操作,并不能保证x的可见性,要保证可见性还是要加同步的,所以严格意义上都得要加同步)
网络上关于第一道题的解答可以见以下几个链接:
http://www.parallellabs.com/2010/04/15/atomic-operation-in-multithreaded-application/
http://blog.chinaunix.net/uid-669974-id-304287.html
http://blog.csdn.net/piaojun_pj/article/details/5924389
第二道题是我自己对于第一道题的扩展,对于一个long型数据,做了个赋值操作,在32系统下需要经过两步才能完成,先修改低32位,然后修改高32位,所以在32位的操作系统上第二道题里的都得加同步。
2、概念定义
原子操作:即不能被线程调度机制中断的操作
通常所说的原子操作包括对非long和double型的primitive进行赋值,以及返回这两者之外的primitive。要在线程间共享long或double的字段时,必须在synchronized中操作。
多线程加锁的规律表(这张表来源网络,但是我觉得有问题,因为long、double是不符合下表的):下表中的简单数据类型为除long,double, long与double的读写需要加锁
3、扩展,谈些自己的看法
这里所说的原子操作偏向于硬件了,其实个人觉得原子操作是个相对的概念,比如C++语言内某个操作可能是原子操作,但是到了java里就不是了,这个也是看虚拟机的支持。在JVM里,其实还可能存在一些可以看做原子操作的操作,比如对String类型的变量赋值(String实例化以后所有的属性都是final的,因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象)等,只要是语言层支持的原子操作,哪怕计算机不支持,那在这个语言内也可以看做原子操作。
下面有些比较好的文章可以阅读:
http://www.ibm.com/developerworks/cn/java/j-jtp11234/ (Java 理论与实践: 流行的原子)
相关引用:
http://blog.chinaunix.net/uid-669974-id-304287.html