1. 变量递增试验

     static /*volatile*/ int shared=0;//volatile也无法保证++操作的原子性
static synchronized int incrShared(){//不加synchronized的话,shared最终结果值小于预期
return ++shared;
}
public static void testIncrShared(String[] args) throws InterruptedException {
shared=0;
Thread[] thrds = new Thread[20];
for(int j=0;j<thrds.length;j++){
thrds[j] = new Thread(new Runnable() {
@Override
public void run() {
for(int k=0;k<1000;k++){
System.out.println(incrShared());
}
}
});
}
for(int j=0;j<thrds.length;j++){
thrds[j].start();
}
for(int j=0;j<thrds.length;j++){
thrds[j].join();
}
System.out.println(shared);
}

2. volatile试验

     static /*volatile*/ int a0,a1;//这里加volatile的话,可以避免r0==r1==0的结果
static /*volatile*/ int r0,r1;//这里即使加volatile,也无法避免r0==r1==0的结果
public static void testVolatile(String[] args) throws InterruptedException {
int[] a=new int[2];
int[] r=new int[2];
final int SLEEP=10;
final Object lock=new Object();
Runnable run1=new Runnable() {
@Override
public void run() {
try {
Thread.sleep(SLEEP);
} catch (InterruptedException e) {
e.printStackTrace();
}
//synchronized (lock) {//加锁也可以建立happens-before关系,避免r0==r1==0的结果
a0=1;
//}
r1=a1;
}
};
Runnable run2=new Runnable() {
@Override
public void run() {
try {
Thread.sleep(SLEEP);
} catch (InterruptedException e) {
e.printStackTrace();
}
//synchronized (lock) {
a1=1;
//}
r0=a0;
}
};
Thread thrd1;
Thread thrd2; int i;
int[][] acnt=new int[2][2];
int[][] rcnt=new int[2][2];
for(i=0;i<10000;i++){
a0=a1=0;
r0=r1=0;
thrd1 = new Thread(run1);
thrd2 = new Thread(run2); thrd1.start();
thrd2.start(); thrd1.join();
thrd2.join(); a[0]=a0;
a[1]=a1;
r[0]=r0;
r[1]=r1;
System.out.println(i);
System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(r));
acnt[a[0]][a[1]]++;
rcnt[r[0]][r[1]]++;
}
System.out.println(Arrays.deepToString(acnt));
System.out.println(Arrays.deepToString(rcnt));
}

3. volatile试验2

     static boolean shouldStop=false;
public static void testVolatile2(String[] args) throws InterruptedException {
shouldStop=false;
Runnable run1=new Runnable() {
@Override
public void run() {
int i=0;
while (!shouldStop) {//无法读取到线程2修改后的shouldStop值,导致无限循环
i++;
//System.out.println(i);//如果调用其他函数的话,就又可以读取到shouldStop的最新值了
}
}
};
Runnable run2=new Runnable() {
@Override
public void run() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
shouldStop=true;
}
};
Thread thrd1;
Thread thrd2; int i;
int[][] acnt=new int[2][2];
int[][] rcnt=new int[2][2];
for(i=0;i<100;i++){
thrd1 = new Thread(run1);
thrd2 = new Thread(run2); thrd1.start();
thrd2.start(); thrd2.join();
System.out.println(i);
System.out.println(shouldStop);
thrd1.join(); }
}

Java线程安全 关于原子性与volatile的试验的更多相关文章

  1. 【Java并发】1. Java线程内存模型JMM及volatile相关知识

    Java招聘知识合集:https://www.cnblogs.com/spzmmd/tag/Java招聘知识合集/ 该系列用于汇集Java招聘需要的知识点 JMM 并发编程的三大特性:可见性(vola ...

  2. Java 线程 — synchronized、volatile、锁

    线程同步基础 synchronized 和volatile是Java线程同步的基础. synchronized 将临界区的内容上锁,同一时刻只有一个进程能访问该临界区代码 使用的是内置锁,锁一个时刻只 ...

  3. 【Java线程】volatile的适用场景

    http://www.ibm.com/developerworks/cn/java/j-jtp06197.html 把代码块声明为 synchronized,有两个重要后果,通常是指该代码具有 原子性 ...

  4. Java线程工作内存与主内存变量交换过程及volatile关键字理解

    Java线程工作内存与主内存变量交换过程及volatile关键字理解 1. Java内存模型规定在多线程情况下,线程操作主内存变量,需要通过线程独有的工作内存拷贝主内存变量副本来进行.此处的所谓内存模 ...

  5. Java线程(二):线程同步synchronized和volatile

    上篇通过一个简单的例子说明了线程安全与不安全,在例子中不安全的情况下输出的结果恰好是逐个递增的(其实是巧合,多运行几次,会产生不同的输出结果),为什么会产生这样的结果呢,因为建立的Count对象是线程 ...

  6. java线程之二(synchronize和volatile方法)

    要说明线程同步问题首先要说明Java线程的两个特性,可见性和有序性.多个线程之间是不能直接传递数据交互的,它们之间的交互只能通过共享变量来实现.拿上篇博文中的例子来说明,在多个线程之间共享了Count ...

  7. java线程--volatile实现可见性

    volatile关键字: 1)能够保证volatile变量的可见性 2)不能保证volatile变量复杂操作的原子性. volatile如何实现内存可见性: 深入来说:通过加入内存屏障和禁止重排序优化 ...

  8. java线程安全— synchronized和volatile

    java线程安全— synchronized和volatile package threadsafe; public class TranditionalThreadSynchronized { pu ...

  9. Java线程的概念

    1.      计算机系统 使用高速缓存来作为内存与处理器之间的缓冲,将运算需要用到的数据复制到缓存中,让计算能快速进行:当运算结束后再从缓存同步回内存之中,这样处理器就无需等待缓慢的内存读写了. 缓 ...

随机推荐

  1. Unity3D Layer要点

    简介         Layer可以用于光照的分层和物理碰撞的分层,这样可以很好地进行性能优化 数据结构         Layer在Unity中有3中呈现方式:1.string名字,2.int层索引 ...

  2. centOS下调整swap

    [root@localhost /]# mkdir swap [root@localhost /]# cd swap [root@localhost swap]# dd if=/dev/zero of ...

  3. HTML基础学习(一)—HTML

    一.HTML的介绍      HTML(HyperText Markup Language)超文本标记语言,不是一种编程语言,而是一种描述性的标记语言,用于描述超文本的内容的显示,比如字体颜色或者大小 ...

  4. Entity Framework快速入门--IQueryable与IEnumberable的区别

    IEnumerable接口 公开枚举器,该枚举器支持在指定类型的集合上进行简单迭代.也就是说:实现了此接口的object,就可以直接使用foreach遍历此object: IQueryable 接口 ...

  5. Ant Design 的一个练习小Demo

    Ant Design 由蚂蚁金服团队出品, 基于 React 的组件化开发模式,封装了一套丰富而实用的 UI 组件库. 在这个练习Demo 中,按照 Ant Design 官网的教程示例,尝试使用 A ...

  6. 【shell编程基础1】shell变量篇

    Bash shell bash shell 是bourne shell 的升级版,“bourne again shell”.ubuntu的默认shell. 预备知识 1. "#!" ...

  7. 【卸载】oracle卸载

    Oracle卸载比较麻烦,不能简单卸载就完成了,有时没有卸载完整,下次安装不能很好的安装: 当然Oracle卸载也没有那么难,只是步骤比较多.Oracle10g还是Oracle11g卸载步骤都是一样的 ...

  8. php 启动过程 - sapi MINIT 过程

    php 启动过程 - sapi MINIT 过程 sapi 概念 sapi 是 php 的应用编程接口, server 端接收请求通过 sapi 接口层交给 php 处理 不同的 server 端底层 ...

  9. IEnumerable<T>和IQueryable<T>

    建议29.区别LINQ查询中的IEnumerable<T>和IQueryable<T> LINQ查询方法一共提供了两类扩展方法,在System.Linq命名空间下,有两个静态类 ...

  10. Java 设计模式(四)-工厂方法模式 (FactoryMethod Pattern)

    1     概念定义 1.1   定义 定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类. 1.2   类型 创建类模式 2     原理特征 2.1   类 ...