简单的说就是:
原子性,不被线程调度器中断的操作,同一时间只有一个线程进行操作,若存在多个线程同时操作的话,就存在线程安全的因素了,是非原子性的。synchronized为一段操作或内存进行加锁,它具有互斥性。当线程要操作被synchronized修饰的内存或操作时,必须首先获得锁才能进行后续操作;但是在同一时刻只能有一个线程获得相同的一把锁,保证了线程安全,相当于将非原子性操作转化为了原子性。
可见性,是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的,操作状态多线程之间互相可见。volatile让变量每次在使用的时候,都从主存中取。而不是从各个线程的“工作内存”。volatile具有synchronized关键字的“可见性”,但是没有synchronized关键字的“并发正确性”,也就是说不保证线程执行的有序性。volatile变量对于每次使用,线程都能得到当前volatile变量的最新值,但是volatile变量并不保证并发的正确性。
举个简单的例子:
多线程并发操作count++,
cup的执行过程是:
1.将count值从内存加载到cup的寄存器A(备份过程);
2.将A中的count值+1(计算),将A中的count计算结果值存放到寄存器B(缓存区);
3.在某些“恰当的”时刻,cup将寄存器B中的count值写回到内存
(注:这样做的好处是减少对内存的读取,提高执行效率)
那么,并发状态下,count值在A中的计算结果在写入内存之前,止步于缓存区状态,各线程之间不能获取其他线程的操作结果,这是不可见性。
关键字volatile修饰count,执行上述操作:
1.将count值从内存加载到cup的寄存器A(备份过程);
2.将A中的count值+1(计算),将A中的count计算结果值存放到寄存器B(缓存区);
3.将寄存器中的count值写回到内存(同步执行)。
count值在A中的计算结果同时写入缓存区和内存中,各线程之间能获取其他线程的操作结果,这是可见性。
但是这种情况,依然存在线程安全问题,多线程并发操作获取内存中的count值可能相同(计算结果还未写入内存),多线程同时执行计算,即使计算多次,依然相当于就算了一次,这是非原子性。
简单总结:
synchronized保证了原子性和可见性
volatile仅仅保证了可见性
多线程原子性和可见性
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 第三章 Java内存模型 3.1 Java内存模型的基础 通信在共享内存的模型里,通过写-读内存中的公共状态进行隐...
- 本文基于周志明的《深入理解java虚拟机 JVM高级特性与最佳实践》所写。特此推荐。 衡量一个服务性能的高低好坏,...