public class VolatileTest {
public static void main(String[] args) {
ThreadDemo td = new ThreadDemo();
new Thread(td).start();
while(true){
if(td.getFlag()){
System.out.println("========");
break;
}
} }
}
class ThreadDemo implements Runnable{
private boolean flag=false; @Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag=true;
System.out.println("flag="+getFlag()); }
public boolean getFlag(){
return flag;
}
}

flag是main thread和td共享的数据,他们都在各自的线程内有一个copy,由于while true的速度十分快,main thread不能读取到td修改后的值,所以只能输出 flag=true。

内存不可见性:当多个thread操作共享数据时,彼此不可见

volatile:当多个thread操作共享数据时,保证数据是可见的,内存栅栏   可以理解为多个线程直接操作主存中的数据

因为使用vloatile 不能指令重排  所以效率低

volatile相比synchronized:

  是一种较为轻量级的同步策略,volatile不具备互斥性,两个线程可以同时访问共享数据,volatile不能保证变量的原子性,

原子性问题:i++

  

以下情况使用volatile不能解决非原子性问题:内存可见性问题依然存在

public class AtomicTest {
public static void main(String[] args) {
AtomicDemo ad = new AtomicDemo();
for(int i=0;i<10;i++){
new Thread(ad).start();
}
}
}
class AtomicDemo implements Runnable{
private int serialNum=0;
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+getSerialNum());
}
public int getSerialNum(){
return serialNum++;
}
}

二、使用源自变量 java.util.concurrent.atomic 原子变量包

  1.使用volatile保证内存可见性

  2.使用CAS compare and swap算法保证数据的原子性

    CAS是硬件对于并发操作共享数据的支持  

    CAS包含三个操作数:

      内存值V 预估值A 更新值B

(1)首先读取内存之V 在替换的时候读取旧值A

AtomicInteger:保证线程安全  内存可见性 原子性问题

private AtomicInteger serialNum=new AtomicInteger();
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+getSerialNum());
}
public int getSerialNum(){
return serialNum.getAndIncrement();
}

CAS算法的模拟:

public class TestCAS {
public static void main(String[] args) {
final CompareAndSwap cas = new CompareAndSwap(); for(int i=0;i<10;i++){
new Thread(new Runnable() {
@Override
public void run() {
int expectVal = cas.get();
boolean b= cas.compareAndSwap(expectVal,(int)(Math.random()*101));
}
}).start();
}
}
} class CompareAndSwap {
private int value;
public synchronized int get() {
return value;
}
public synchronized int cas(int expectVal, int newVal) {
int oldVal = value;
if (oldVal == expectVal)
this.value = newVal;
return oldVal;
}
public synchronized boolean compareAndSwap(int expectVal, int newVal) {
return expectVal==cas(expectVal,newVal);
}
}

最新文章

  1. jQuery插件开发(溢出滚动)
  2. SQL判断某列中是否包含中文字符、英文字符、纯数字 (转)
  3. 【BZOJ 2190】【SDOI 2008】仪仗队 欧拉筛
  4. 使用jquery构建Metro style 返回顶部
  5. (转)C# Base64
  6. 创建xml时,设置xml编码问题
  7. 对.NET中Hashtable和ArryList的理解
  8. Java 计算两个日期相差月数
  9. MemoryMappedFile 内存映射文件 msdn
  10. J2SE知识点摘记(二十二)
  11. appium locator
  12. EasyUI - According 分类列表
  13. [基础]RHEL6下LINUX服务器批量部署
  14. Hibernate配置文件中配置各种数据库的driver、URL
  15. 【开发技术】Xcode3与xcode4.2模板对比(Xcode4.2开发之一些变化)
  16. Hadoop2.x 体系结构和源码编译
  17. maven安装、配置
  18. js中获取时间new date()的用法
  19. DIY 空气质量检测表
  20. pc版qq登录及移动版qq登录的申请过程

热门文章

  1. DevOps时代,企业数字化转型需要强大的工具链
  2. Django-5 模板层
  3. SpringCloud---网关概念、Zuul项目搭建(六)
  4. 快速实现兼容的js复制方式。有点非正规,通过非正规的排版实现。
  5. vedio-js的视频插件用法
  6. 基于zookeeper实现分布式锁
  7. 解决Windows10中Virtualbox安装虚拟机没有64位选项
  8. C# AddRange为数组添加多个元素的代码
  9. layui——Cannot create property &#39;LAY_TABLE_INDEX&#39; on number &#39;1&#39;
  10. ACM-ICPC 2018 徐州赛区网络预赛 HRyuji doesn&#39;t want to study 树状数组