synchronized和volatile关键字
synchronized
同步块大家都比较熟悉,通过 synchronized 关键字来实现,所有加上synchronized 和 块语句,在多线程访问的时候,同一时刻只能有一个线程能够用 synchronized 修饰方法或者代码块。
volatile
用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的值。volatile很容易被误用,用来进行原子性操作。
以下两段程序演示了两者区别
package net.dp.volatileTest;
public class JoinThread extends Thread {
public static volatile int n = 0;
public void run() {
for (int i = 0; i < 10; i++)
try {
n = n + 1;
sleep(3); // 为了使运行结果更随机,延迟3毫秒
} catch (Exception e) {
}
}
public static void main(String[] args) throws Exception {
Thread threads[] = new Thread[100];
for (int i = 0; i < threads.length; i++)
// 建立100个线程
threads[i] = new JoinThread();
for (int i = 0; i < threads.length; i++)
// 运行刚才建立的100个线程
threads[i].start();
for (int i = 0; i < threads.length; i++)
// 100个线程都执行完后继续
threads[i].join();
System.out.println(" n= " + JoinThread.n);
//执行结果 n < 1000
}
}
程序的运行结果是n小于1000.
原因:Java在创建线程的时候会为每一个线程分配线程当前的内存空间用来存放当前线程中的变量,存储在栈中;这些变量最终的值是存储在堆中。也就是说栈中会有堆中变量值的副本。volatile关键字是保证不同线程对该变量的访问是从堆中获取,拿到的是同一个变量的真实值不是栈中的副本。但是这并不能保证该操作是原子性的。在程序中n = n + 1操作就不是原子性的所以才会出错。
使用synchronized关键字解决该问题。
package net.dp.volatileTest;
public class JoinThread2 extends Thread {
public static int n = 0;
public static synchronized void inc() {
n++;
}
public void run() {
for (int i = 0; i < 10; i++)
try {
inc(); // n = n + 1 改成了 inc();
sleep(3); // 为了使运行结果更随机,延迟3毫秒
} catch (Exception e) {
}
}
public static void main(String[] args) throws Exception {
Thread threads[] = new Thread[100];
for (int i = 0; i < threads.length; i++)
// 建立100个线程
threads[i] = new JoinThread2();
for (int i = 0; i < threads.length; i++)
// 运行刚才建立的100个线程
threads[i].start();
for (int i = 0; i < threads.length; i++)
// 100个线程都执行完后继续
threads[i].join();
System.out.println(" n= " + JoinThread2.n);
}
}
程序执行结果是1000
使用synchronized关键字对自增操作修饰,保证了自增的原子操作。
synchronized和volatile关键字的更多相关文章
- 10-Java中共享内存可见性以及synchronized和volatile关键字
Java中共享变量的内存可见性 我们首先来看一下在多线程下处理共享变量时Java的内存模型,如图所示 Java内存模型规定,将所有的变量都存放在主存中,当线程使用变量的时候,会把主内存里面的变量赋值到 ...
- Java并发编程学习笔记 深入理解volatile关键字的作用
引言:以前只是看过介绍volatile的文章,对其的理解也只是停留在理论的层面上,由于最近在项目当中用到了关于并发方面的技术,所以下定决心深入研究一下java并发方面的知识.网上关于volatile的 ...
- volatile关键字的作用
引言:以前只是看过介绍volatile的文章,对其的理解也只是停留在理论的层面上,由于最近在项目当中用到了关于并发方面的技术,所以下定决心深入研究一下java并发方面的知识.网上关于volatile的 ...
- volatile关键字的介绍和使用
关键字volatile的主要作用是使变量在过个线程中可见 1.假设volatile不存在我们将会面对的问题 public class PrintString implements Runnable { ...
- java面试记录二:spring加载流程、springmvc请求流程、spring事务失效、synchronized和volatile、JMM和JVM模型、二分查找的实现、垃圾收集器、控制台顺序打印ABC的三种线程实现
注:部分答案引用网络文章 简答题 1.Spring项目启动后的加载流程 (1)使用spring框架的web项目,在tomcat下,是根据web.xml来启动的.web.xml中负责配置启动spring ...
- [面试必备]深入理解Java的volatile关键字
前言 在Java并发编程中,volatile关键字有着至关重要的作用,在面试中也常常会是必备的一个问题.本文将会介绍volatile关键字的作用以及其实现原理. volatile作用 volatile ...
- Java多线程6:synchronized锁定类方法、volatile关键字及其他
同步静态方法 synchronized还可以应用在静态方法上,如果这么写,则代表的是对当前.java文件对应的Class类加锁.看一下例子,注意一下printC()并不是一个静态方法: public ...
- volatile关键字和synchronized关键字
volatile关键字: 可以用来修饰字段(成员变量),就是告知程序任何对该变量的访问均需要从共享内存中获取,而对它的改变必须同步刷新回共享内存,它能保证所有线程对变量访问的可见性. synchron ...
- 并发编程之ThreadLocal、Volatile、synchronized、Atomic关键字扫盲
前言 对于ThreadLocal.Volatile.synchronized.Atomic这四个关键字,我想一提及到大家肯定都想到的是解决在多线程并发环境下资源的共享问题,但是要细说每一个的特点.区别 ...
随机推荐
- 【转载】巴塞尔问题(Basel Problem)的多种解法
如何计算 \(\displaystyle \zeta \left ( 2 \right )=\frac{1}{1^{2}}+\frac{1}{2^{2}}+\frac{1}{3^{2}}+\cdots ...
- Docker容器CPU限制选项测试
目录 Docker容器CPU限制选项测试 参考 实验环境 --cpu-shares选项 测试 结论 --cpus选项 测试 结论 --cpuset-cpus选项 测试 结论 Docker容器CPU限制 ...
- Fluent_Python_Part3函数即对象,06-dp-1class-func,一等函数与设计模式
使用一等函数实现设计模式 中文电子书P278 合理利用作为一等对象的函数,把模式中涉及的某些类的实例替换成简单的函数,从而简化代码. 1. 重构"策略"模式 中文电子书P282 P ...
- [0CTF 2016] piapiapia
一道非常有意思的反序列化漏洞的题目 花费了我不少时间理解和记忆 这里简单记录其中精髓 首先打开是一个登陆页面 dirsearch扫描到了www.zip源码备份 update.php <?php ...
- acm数论之旅(转载)---最大公约数与最小公倍数
gcd(a, b),就是求a和b的最大公约数 lcm(a, b),就是求a和b的最小公倍数 然后有个公式 a*b = gcd * lcm ( gcd就是gcd(a, b), ( •̀∀•́ ) ...
- Java基础题目
题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子对数为多少? 程序分析:兔子的规律为数列1,1,2,3,5,8, ...
- CocosCreator内存与性能优化
一.内存优化 因为 iOS小游戏和微信共用同一个进程,而微信在连续两次收到系统内存警告的时候会关闭小游戏并释放小游戏占用的内存.如果你的小游戏有外网用户反馈“闪退”,或者你自己测试的时候频繁出现“该小 ...
- javascript 原型继承 与class extends 继承对比
//父类 Animal function Animal (name) { this.name = name; this.sleep = function () { console.log(this ...
- office 2016
Excel 2016: F4 : 重复上一步操作. 例子: 如果上一步是合并单元格, 则 再次选中其他几个单元格, F4即再次完成合并. 单元格中插入对角线: 选中单元格, 右键--设置单元格格式- ...
- Laravel 6.X 数据库迁移 创建表 与 修改表
数据库迁移创建表 本篇文章中使用的是mysql数据库,其他数据库需要修改env文件和app配置,请其他地方搜索一下就会找到. 创建示例 1.创建users表: 命令行键入 php artisan ma ...