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. 计算机系统 使用高速缓存来作为内存与处理器之间的缓冲,将运算需要用到的数据复制到缓存中,让计算能快速进行:当运算结束后再从缓存同步回内存之中,这样处理器就无需等待缓慢的内存读写了. 缓 ...
随机推荐
- SharePoint JavaScript 客户端对象使用视频教程
本次视频教程是为大家介绍如何使用SharePoint JavaScript客户端对象,包括对于站点.列表.文档库.列表项.文件夹.文件和附件等基本对象的操作,同时,为大家举几个简单的应用的例子,让大家 ...
- 关于微信小程序图片失真的解决方案
今天来说一说 关于微信小程序的图片失真问题的解决,微信小程序的image标签要设置其宽高,不然图片若宽高过大会撑开原始图片大小的区域:如下 但是宽高设置固定了会导致有些图片和规定显示图片大小的比例不一 ...
- 微服务架构的简单实现-Stardust
微服务架构,一个当下比较火的概念了.以前也只是了解过这方面的概念,没有尝试过.想找找.NET生态下面是否有现成的实现,可是没找到,就花了大半个月的闲暇时间,遵循着易用和简单,实现了一个微服务框架,我叫 ...
- Ubuntu 12.4 server 安装 redmine
1,安装默认的redmine apt-get install apache2 libapache2-mod-passenger mysql-server redmine redmine-mysql 直 ...
- Java基础学习(二)—数组
一.数组的概念 定义: 数组是存储同一种数据类型的多个元素的集合. 数组既可以存储基本数据类型,也可以存储引用数据类型. 格式: 格式1: 数据类型[] 数组名; 格式2: 数据类型 数组名[]; 这 ...
- var的一些理解
var 是 variable(变量,可变物)的简写.在多种编程语言中,var 被用作定义变量的关键字,在一些操作系统中也能见到它的身影.类似object,但是效率比object高一点. var是一个局 ...
- Apache设置404页面
使用版本:Apache 2.2 1.添加404页面 在所配置网站的根目录添加编辑好的 404.html (页面名字无所谓 比如也可以叫missing.html) 如C:\Program Files\A ...
- 【one day one linux】linux下的软件包管理工具
Linux 下的软件包管理工具 linux下的软件安装可以通过两种方式,一种是直接使用自带的软件包管理工具安装,另外一种通过编译源码安装. 1.软件包的种类 Red Hat和Fedora:redhat ...
- 【Tomcat源码学习】-2.容器管理
Tomcat作为应用服务器,我们可以理解Tomcat本身就是一个容器,用于装载应用,而作为容器本身是由若干组件以及事件构成,容器管理即为管理容器的有机组成部分. 一.Tomcat整体结构: Ser ...
- java集合的操作(set,Iterator)
集合的操作 Iterator.Collection.Set和HashSet关系 Iterator<——Collection<——Set<——HashSet Iterator中的方法: ...