synchronized实现可见性
JMM关于synchronized的两条规定:
1)线程解锁前,必须把共享变量的最新值刷新到主内存中
2)线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新获取最新的值
(注意:加锁与解锁需要是同一把锁)
通过以上两点,可以看到synchronized能够实现可见性。同时,由于synchronized具有同步锁,所以它也具有原子性
多线程中程序交错执行时,重排序可能会造成内存可见性问题
接下来我们看一段代码:
/**
* synchronized能够实现原子性(同步)、可见性
*
* @author xuwenjin
*/
public class SynchronizedDemo { //共享变量
private boolean ready = false;
private int result = ;
private int number = ; /**
* 写操作
*/
public void write() {
ready = true; //1.1
number = ; //1.2
} /**
* 读操作
*/
public void read() {
if (ready) { //2.1
result = number * ; //2.2
}
System.out.println("result:" + result);
} //内部线程类
private class WriteReadThread extends Thread { private boolean flag = false; public WriteReadThread(boolean flag){
this.flag = flag;
} @Override
public void run() {
if (flag) {
write();
}else {
read();
}
}
} public static void main(String[] args) {
SynchronizedDemo demo = new SynchronizedDemo();
//启动线程执行写操作
demo.new WriteReadThread(true).start();
//启动线程执行读操作
demo.new WriteReadThread(false).start();
} }
上面的代码可能出现如下执行顺序:
1) 1.1 --> 1.2 --> 2.1--> 2.2 result的值为 (正常情况)
2) 1.1 --> 2.1 --> 2.2 --> 1.2 result的值为 (当写线程执行完1.1之后,读线程开始)
3) 1.2 --> 2.1 --> 2.2 --> 1.1 result的值为 (1.1跟1.2重排序)
4)...
当然由于重排序和线程的交叉执行,还可能出现很多种执行顺序
导致共享变量在线程间不可见的原因:
a、线程的异步执行
b、重排序结合线程交叉执行
c、共享变量更新后的值没有在工作内存与主内存间及时更新
那么如何解决可见性的问题呢?接下来我们的主角出场:synchronized
安全的代码:
/**
* 写操作
*/
public synchronized void write() {
ready = true; //1.1
number = ; //1.2
} /**
* 读操作
*/
public synchronized void read() {
if (ready) { //2.1
result = number * ; //2.2
}
System.out.println("result:" + result);
}
由于synchronized的原子性、可见性,可以完美解决以上说的三点问题。不过读线程和写线程的执行顺序是不定的,所以result的结果仍然会出现6或0。
如何保证线程顺序执行,大家可参考:https://blog.csdn.net/wenxingchen/article/details/78026767
synchronized实现可见性的更多相关文章
- synchronized的可见性理解
之前的时候看<并发编程的艺术>,书中提到dcl写法的单例模式是有问题的,有可能会导致调用者得到一个创建了一半的对象,从而导致报错.修复办法是将单例对象的引用添加volatile进行修饰,禁 ...
- java synchronized实现可见性对比volatile
问题: 大家可以先看看这个问题,看看这个是否有问题呢? 那里有问题呢? public class ThreadSafeCache { int result; public int getResult( ...
- 关于synchronized 影响可见性的问题
问题来自于学习thinking in java的时候的一个示例,先上代码吧 public class StopThread { private static boolean stop = false; ...
- Volatile和Synchronized对可见性和原子性的支持
在学习并发编程的时候,遇见了volatile和synchronized关键字问题,volatile是可以保证可见性,但无法保证原子性,synchronized关键字由于其是加锁机制,肯定是可以保证原子 ...
- synchronized内存可见性理解
一.背景 最近在看<Java并发编程实战>这本书,看到共享变量的可见性,其中说到"加锁的含义不仅仅局限于互斥行为,还包括内存可见性". 我对于内存可见性第一反应是vol ...
- java线程-synchronized实现可见性代码
以下是一个普通线程代码: package com.Sychronized; public class SychronizedDemo { //共享变量 private boolean ready=fa ...
- volatile、Synchronized实现变量可见性的原理,volatile使用注意事项
变量不可见的两个原因 Java每个线程工作都有一个工作空间,需要的变量都是从主存中加载进来的.Java内存模型如下(JMM): 线程访问一个共享的变量时,都需要先从主存中加载一个副本到自己的工作内存中 ...
- 1 Java线程的内存可见性
Java内存的可见性 可见性: 一个线程对共享变量的修改,能够及时被其它线程看到 共享变量: 如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量 Java内存模型(JM ...
- 细说Java多线程之内存可见性
编程这些实践的知识技能,每一次学习使用可能都会有新的认识 一.细说Java多线程之内存可见性(数据挣用) 1.共享变量在线程间的可见性 共享变量:如果一个 ...
随机推荐
- .NET高级代码审计(第二课) Json.Net反序列化漏洞
0X00 前言 Newtonsoft.Json,这是一个开源的Json.Net库,官方地址:https://www.newtonsoft.com/json ,一个读写Json效率非常高的.Net库,在 ...
- 微软官方实例 RazorPagesMovie 在 asp.net core 2.1 版本下的实战
微软官方实例 RazorPagesMovie 在 asp.net core 2.1 版本下的实战 友情提示: 操作系统: MacOS 10.13.5 dotnet core: version 2.1. ...
- 403 - 禁止访问: 访问被拒绝(IIS)
错误如下: 解决方法: 1,点击当前网站主页,选择默认文档 2,添加网站的起始页,我这里是main.htm
- Linq to SQL 参考Demo
LINQ to SQL语句()之Where Where操作 适用场景:实现过滤,查询等功能. 说明:与SQL命令中的Where作用相似,都是起到范围限定也就是过滤作用的,而判断条件就是它后面所接的子句 ...
- c# 输入姓名直到输入的是quit时,停止输入然后显示出输入的姓名个数及姓名
1.输入姓名直到输入的是quit时(不区分大小写),停止输入然后显示出输入的姓名个数及姓名: 要求结果如下图所示: class Program { static void Main(string[] ...
- Uliweb之 ORM基本使用(Sqlalchemy)
参考:http://limodou.github.io/uliweb-doc/zh_CN/db/orm.html#title_1-2 ORM基本使用¶ 使用要求¶ 需要安装sqlalchemy 0.7 ...
- Day 29 _模块二 -hashlib_configparse_logging
一.hashlib Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等. 什么是摘要算法呢?摘要算法又称哈希算法.散列算法.它通过一个函数,把任意长度的数据转换为一个长度固定的数 ...
- JQuery - 动态添加Html后,如何使CSS生效,JS代码可用?
今天在开发JQuery Mobile程序时候,需要从服务器取得数据,随后显示在页面上的Listview控件中,数据完整获取到了,也动态添加到Listview控件中,但是数据对应的CSS没有任何效果了, ...
- flask源码解析之session
内容回顾 cookie与session的区别: 1. session 是保存在服务端的键值对 2. cookie 只能保存4096个字节的数据,但是session不受限制 3. cookie保存在浏览 ...
- Storm Trident API
在Storm Trident中有五种操作类型 Apply Locally:本地操作,所有操作应用在本地节点数据上,不会产生网络传输 Repartitioning:数据流重定向,单纯的改变数据流向,不会 ...