Java线程安全 关于原子性与volatile的试验
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的试验的更多相关文章
- 【Java并发】1. Java线程内存模型JMM及volatile相关知识
Java招聘知识合集:https://www.cnblogs.com/spzmmd/tag/Java招聘知识合集/ 该系列用于汇集Java招聘需要的知识点 JMM 并发编程的三大特性:可见性(vola ...
- Java 线程 — synchronized、volatile、锁
线程同步基础 synchronized 和volatile是Java线程同步的基础. synchronized 将临界区的内容上锁,同一时刻只有一个进程能访问该临界区代码 使用的是内置锁,锁一个时刻只 ...
- 【Java线程】volatile的适用场景
http://www.ibm.com/developerworks/cn/java/j-jtp06197.html 把代码块声明为 synchronized,有两个重要后果,通常是指该代码具有 原子性 ...
- Java线程工作内存与主内存变量交换过程及volatile关键字理解
Java线程工作内存与主内存变量交换过程及volatile关键字理解 1. Java内存模型规定在多线程情况下,线程操作主内存变量,需要通过线程独有的工作内存拷贝主内存变量副本来进行.此处的所谓内存模 ...
- Java线程(二):线程同步synchronized和volatile
上篇通过一个简单的例子说明了线程安全与不安全,在例子中不安全的情况下输出的结果恰好是逐个递增的(其实是巧合,多运行几次,会产生不同的输出结果),为什么会产生这样的结果呢,因为建立的Count对象是线程 ...
- java线程之二(synchronize和volatile方法)
要说明线程同步问题首先要说明Java线程的两个特性,可见性和有序性.多个线程之间是不能直接传递数据交互的,它们之间的交互只能通过共享变量来实现.拿上篇博文中的例子来说明,在多个线程之间共享了Count ...
- java线程--volatile实现可见性
volatile关键字: 1)能够保证volatile变量的可见性 2)不能保证volatile变量复杂操作的原子性. volatile如何实现内存可见性: 深入来说:通过加入内存屏障和禁止重排序优化 ...
- java线程安全— synchronized和volatile
java线程安全— synchronized和volatile package threadsafe; public class TranditionalThreadSynchronized { pu ...
- Java线程的概念
1. 计算机系统 使用高速缓存来作为内存与处理器之间的缓冲,将运算需要用到的数据复制到缓存中,让计算能快速进行:当运算结束后再从缓存同步回内存之中,这样处理器就无需等待缓慢的内存读写了. 缓 ...
随机推荐
- Unity3D Layer要点
简介 Layer可以用于光照的分层和物理碰撞的分层,这样可以很好地进行性能优化 数据结构 Layer在Unity中有3中呈现方式:1.string名字,2.int层索引 ...
- centOS下调整swap
[root@localhost /]# mkdir swap [root@localhost /]# cd swap [root@localhost swap]# dd if=/dev/zero of ...
- HTML基础学习(一)—HTML
一.HTML的介绍 HTML(HyperText Markup Language)超文本标记语言,不是一种编程语言,而是一种描述性的标记语言,用于描述超文本的内容的显示,比如字体颜色或者大小 ...
- Entity Framework快速入门--IQueryable与IEnumberable的区别
IEnumerable接口 公开枚举器,该枚举器支持在指定类型的集合上进行简单迭代.也就是说:实现了此接口的object,就可以直接使用foreach遍历此object: IQueryable 接口 ...
- Ant Design 的一个练习小Demo
Ant Design 由蚂蚁金服团队出品, 基于 React 的组件化开发模式,封装了一套丰富而实用的 UI 组件库. 在这个练习Demo 中,按照 Ant Design 官网的教程示例,尝试使用 A ...
- 【shell编程基础1】shell变量篇
Bash shell bash shell 是bourne shell 的升级版,“bourne again shell”.ubuntu的默认shell. 预备知识 1. "#!" ...
- 【卸载】oracle卸载
Oracle卸载比较麻烦,不能简单卸载就完成了,有时没有卸载完整,下次安装不能很好的安装: 当然Oracle卸载也没有那么难,只是步骤比较多.Oracle10g还是Oracle11g卸载步骤都是一样的 ...
- php 启动过程 - sapi MINIT 过程
php 启动过程 - sapi MINIT 过程 sapi 概念 sapi 是 php 的应用编程接口, server 端接收请求通过 sapi 接口层交给 php 处理 不同的 server 端底层 ...
- IEnumerable<T>和IQueryable<T>
建议29.区别LINQ查询中的IEnumerable<T>和IQueryable<T> LINQ查询方法一共提供了两类扩展方法,在System.Linq命名空间下,有两个静态类 ...
- Java 设计模式(四)-工厂方法模式 (FactoryMethod Pattern)
1 概念定义 1.1 定义 定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类. 1.2 类型 创建类模式 2 原理特征 2.1 类 ...