JAVA的原子性和可见性,线程同步的理解
1、原子性
(1)原子是构成物质的基本单位(当然电子等暂且不论),所以原子的意思代表着——“不可分”;
(2)原子性是拒绝多线程操作的,不论是多核还是单核,具有原子性的量,同一时刻只能有一个线程来对它进行操作。简而言之,在整个操作过程中不会被线程调度器中断的操作,都可认为是原子性。例如 a=1是原子性操作,但是a++和a +=1就不是原子性操作。
2、非原子性
(1)也就是整个过程中会出现线程调度器中断操作的现象,例如:
类似"a += b"这样的操作不具有原子性,在某些JVM中"a += b"可能要经过这样三个步骤:
(1)取出a和b
(2)计算a+b
(3)将计算结果写入内存
如果有两个线程t1,t2在进行这样的操作。t1在第二步做完之后还没来得及把数据写回内存就被线程调度器中断了,于是t2开始执行,t2执行完毕后t1又把没有完成的第三步做完。这个时候就出现了错误,相当于t2的计算结果被无视掉了。所以上面的买碘片例子在同步add方法之前,实际结果总是小于预期结果的,因为很多操作都被无视掉了。
类似的,像"a++"这样的操作也都不具有原子性。所以在多线程的环境下一定要记得进行同步操作。
3、可见性
可见性volatile修饰词,可以应对多线程同时访问修改同一变量,由于相互的不可见性所带来的不可预期的结果,存在二义性的现象,出现的。
多线程变量不可见:当一个线程对一变量a修改后,还没有来得及将修改后的a值回写到主存,而被线程调度器中断操作(或收回时间片),然后让另一线程进行对a变量的访问修改,这时候,后来的线程并不知道a值已经修改过,它使用的仍旧是修改之前的a值,这样修改后的a值就被另一线程覆盖掉了。
多线程变量可见:被volatile修饰的成员变量在每次被线程访问时,都强迫从内存中重读该成员变量的值;而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存,这样在任何时刻两个不同线程总是看到某一成员变量的同一个值,这就是保证了可见性。
volatile使用场景:在两个或者更多的线程访问的成员变量上使用volatile。当要访问的变量已在synchronized代码块中,或者为常量时,不必使用。
由于使用volatile屏蔽掉了JVM中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字。
注意:
如果给一个变量加上volatile修饰符,就相当于:每一个线程中一旦这个值发生了变化就马上刷新回主存,使得各个线程取出的值相同。编译器不要对这个变量的读、写操作做优化。但是值得注意的是,除了对long和double的简单操作之外,volatile并不能提供原子性。所以,就算你将一个变量修饰为volatile,但是对这个变量的操作并不是原子的,在并发环境下,还是不能避免错误的发生!
4、synchronized
synchronized为一段操作或内存进行加锁,它具有互斥性。当线程要操作被synchronized修饰的内存或操作时,必须首先获得锁才能进行后续操作;但是在同一时刻只能有一个线程获得相同的一把锁(对象监视器),所以它只允许一个线程进行操作。
JAVA的原子性和可见性,线程同步的理解的更多相关文章
- Java中线程同步的理解 - 其实应该叫做Java线程排队
Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可 ...
- java中线程同步的理解(非常通俗易懂)
转载至:https://blog.csdn.net/u012179540/article/details/40685207 Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运 ...
- Java并发编程:Java中的锁和线程同步机制
锁的基础知识 锁的类型 锁从宏观上分类,只分为两种:悲观锁与乐观锁. 乐观锁 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新 ...
- Java多线程--原子性、可见性、有序性
计算机的内存模型: 计算机在运行行程序的时候,指令由CPU执行,计算机上数据存放在物理内存当中,CPU在执行指令的时候免不了要和数据打交道.刚开始,还相安无事的,但是随着CPU技术的发展,CPU的执行 ...
- Java进击C#——语法之线程同步
上一章我们讲到关于C#线程方向的应用.但是笔者并没有讲到多线程中的另一个知识点--同步.多线程的应用开发都有可能发生脏数据.同步的功能或多或少都会用到.本章就要来讲一下关于线程同步的问题.根据笔者这几 ...
- JAVA基础知识之多线程——线程同步
线程安全问题 多个线程同时访问同一资源的时候有可能会出现信息不一致的情况,这是线程安全问题,下面是一个例子, Account.class , 定义一个Account模型 package threads ...
- java多线程之Lock线程同步
1.线程同步: package cn.itcast.heima2; import java.util.concurrent.locks.Lock; import java.util.concurren ...
- java多线程(2) 线程同步
我们对线程访问同一份资源的多个线程之间,来进行协调的这个东西,就是线程同步. 例子1:模拟了多个线程操作同一份资源,可能带来的问题: package com.cy.thread; public c ...
- Java中线程同步的理解
我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可能和其他线程共享一些资源, ...
- Java多线程系列三——实现线程同步的方法
两种实现线程同步的方法 方法 特性 synchronized 不需要显式地加解锁,易实现 ReentrantLock 需要显式地加解锁,灵活性更好,性能更优秀,结合Condition可实现多种条件锁 ...
随机推荐
- Docker:Docker打包Web API成镜像并上传到Docker Hub(2)
Docker官方镜像:https://hub.docker.com/: 本文将把一个webapi制作成docker镜像 一.Docker命令 打开Docker Quickstart,有以下常用的命令 ...
- (已解决)jdk安装 系统找不到文件C:\ProgramData\Oracle\Java\javapath\java.exe
jdk安装好之后,也配置好了环境变量,打开cmd输入javac可以跳出相关信息,可是输入java却一直提示:系统找不到文件C:\ProgramData\Oracle\Java\javapath\jav ...
- Python基础(九) type元类
python元类:type() 元类是python高阶语法. 合理的使用可以减少大量重复性的代码. 元类实际上做了以下三方面的工作: 干涉创建类的过程 修改类 返回修改之后的类 为什么使用元类? ...
- Unicode编码学习
unicode基础知识 简单来说,** unicode 是字符集,utf-8,utf-16,utf-32是编码规则.** unicode 字符集: ttps://unicode-table.com/ ...
- proto 3 语法
一.简介 proto3是新版本的protobuf语法.它简化了部分语法,并扩大了支持的语言,Ruby.C#.目前谷歌推荐只在是用新支持的语言或使用新的gRPC框架的时候使用.proto2和proto3 ...
- shell 三剑客
grep 过滤来自一个文件或标准输入匹配模式内容. 除了grep外,还有egrep.fgrep.egrep是grep的扩展,相当于grep -E.fgrep相当于grep -f,用的少. Usage: ...
- 关闭jtag保留swd
串行线JTAG 配置 (Serial wire JTAG configuration) 位26:24 这些位只能由软件写( 读这些位,将返回未定义的数值) ,用于配置SWJ和跟踪复用功能的I/O ...
- JSONModel(I)
JSONModel使用简介 JSONModel 只需要将你的 model 类继承自 JSONModel ,而同时 model 中的属性名又恰巧可以和 JSON 数据中的 key 名字一样的话,那么非常 ...
- RxJava 详解——简洁的异步操作(二)
上次说的两个例子,事件的发出和消费都是在同一个线程的.如果只用上面的方法,实现出来的只是一个同步的观察者模式.观察者模式本身的目的就是异步机制,因此异步对于 RxJava 是至关重要的.而要实现异步, ...
- Java复制目录/子目录/文件
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import ja ...