synchronized

Volatile与Synchronized的区别

橙三吉。 提交于 2020-04-07 23:13:32
java线程的内存模型 java的线程内存模型中定义了每个线程都有一份自己的共享变量副本(本地内存),里面存放自己私有的数据,其他线程不能直接访问,而一些共享变量则存在主内存中,供所有线程访问。 上图中,如果线程A和线程B要进行通信,就要经过主内存,比如线程B要获取线程A修改后的共享变量的值,要经过下面两步: (1)、线程A修改自己的共享变量副本,并刷新到了主内存中。 (2)、线程B读取主内存中被A更新过的共享变量的值,同步到自己的共享变量副本中。 总结:在java内存模型中,共享变量存放在主内存中,每个线程都有自己的本地内存,当多个线程同时访问一个数据的时候,可能本地内存没有及时刷新到主内存,所以就会发生线程安全问题。 java多线程中的三个特性:   原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。一个很经典的例子就是银行账户转账问题:比如从账户A向账户B转1000元,那么必然包括2个操作:从账户A减去1000元,往账户B加上1000元。这2个操作必须要具备原子性才能保证不出现一些意外的问题。   可见性:当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。   有序性:就是程序执行的顺序按照代码的先后顺序执行。一般来说处理器为了提高程序运行效率,可能会对输入代码进行优化

jvm主内存与工作内存

白昼怎懂夜的黑 提交于 2020-04-07 19:49:08
一、jvm主内存与工作内存 首先,JVM将内存组织为主内存和工作内存两个部分。 主内存主要包括本地方法区和堆。每个线程都有一个工作内存,工作内存中主要包括两个部分,一个是属于该线程私有的栈和对主存部分变量拷贝的寄存器(包括程序计数器PC和cup工作的高速缓存区)。 1.所有的变量都存储在主内存中(虚拟机内存的一部分),对于所有线程都是共享的。 2.每条线程都有自己的工作内存,工作内存中保存的是主存中某些变量的拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。 3.线程之间无法直接访问对方的工作内存中的变量,线程间变量的传递均需要通过主内存来完成。 JVM规范定义了线程对内存间交互操作: Lock(锁定):作用于主内存中的变量,把一个变量标识为一条线程独占的状态。 Read(读取):作用于主内存中的变量,把一个变量的值从主内存传输到线程的工作内存中。 Load(加载):作用于工作内存中的变量,把read操作从主内存中得到的变量的值放入工作内存的变量副本中。 Use(使用):作用于工作内存中的变量,把工作内存中一个变量的值传递给执行引擎。 Assign(赋值):作用于工作内存中的变量,把一个从执行引擎接收到的值赋值给工作内存中的变量。 Store(存储):作用于工作内存中的变量,把工作内存中的一个变量的值传送到主内存中。 Write(写入)

Java同步容器和并发容器

穿精又带淫゛_ 提交于 2020-04-06 21:28:57
同步容器 Java常用的容器有ArrayList、LinkedList、HashMap等等,这些容器都是非线程安全的。 如果有多个线程并发地访问这些容器时,就会出现问题。 因此,在编写程序时,必须要求程序员手动地在任何访问到这些容器的地方进行同步处理,这样导致在使用这些容器的时候非常地不方便。 所以,Java提供了同步容器供用户使用。 在Java中,同步容器主要包括2类: 1)Vector、Stack、HashTable Vector实现了List接口,Vector实际上就是一个数组,和ArrayList类似,但是Vector中的方法都是synchronized方法,即进行了同步措施。 Stack也是一个同步容器,它的方法也用synchronized进行了同步,它实际上是继承于Vector类。 HashTable实现了Map接口,它和HashMap很相似,但是HashTable进行了同步处理,而HashMap没有。 2)Collections类中提供的静态工厂方法创建的类 Collections类是一个工具提供类。在Collections类中提供了大量的方法,比如对集合或者容器进行排序、查找等操作。更重要的是,在它里面提供了几个静态工厂方法来创建同步容器类,如下图所示: 从同步容器的具体实现源码可知,同步容器中的方法采用了synchronized进行了同步

原子性,有序性,可见性

纵饮孤独 提交于 2020-04-06 01:01:14
synchronized (原子性 有序性 可见性) volatile (原子性 可见性) 1.volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。 2.volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的。 3.volatile仅能实现变量的修改可见性,并不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性。 4.volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。 5.volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化。 原子性:所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束 例如:int i = 1; 该语句为原子操作,因为执行这句话后i的值一定是等于1. 反例:int i= 0; i++ ; 其中 i++不是原子操作,在多线程中会有线程安全问题,i++其实分为三个步骤,1. 读取变量i的值;2:对i进行加一的操作;3.将计算后的值再赋值给变量i synchronized :能保证原子操作。1、锁住主内存,2、执行工作内 3、将工作内存写入主内存。4.释放锁

面试TodoList

╄→гoц情女王★ 提交于 2020-04-06 00:12:56
面试TodoList 面试TodoList 第一站深圳 Spring MySQL JVM 多线程 Netty Redis 知乎看到的Java面经,看到其中部分题目有启发性就记下来了,抽时间逐个解决吧。 查看原文 第一站深圳 多个线程同时读写,读线程的数量远远⼤于写线程,你认为应该如何解决 并发的问题?你会选择加什么样的锁? JAVA的AQS是否了解,它是⼲嘛的? 除了synchronized关键字之外,你是怎么来保障线程安全的? 什么时候需要加volatile关键字?它能保证线程安全吗? 线程池内的线程如果全部忙,提交⼀个新的任务,会发⽣什么?队列全部 塞满了之后,还是忙,再提交会发⽣什么? Tomcat本身的参数你⼀般会怎么调整? synchronized关键字锁住的是什么东⻄?在字节码中是怎么表示的?在内 存中的对象上表现为什么? wait/notify/notifyAll⽅法需不需要被包含在synchronized块中?这是为什 么? ExecutorService你⼀般是怎么⽤的?是每个service放⼀个还是⼀个项⽬ ⾥⾯放⼀个?有什么好处? Spring 你有没有⽤过Spring的AOP? 是⽤来⼲嘛的? ⼤概会怎么使⽤? 如果⼀个接⼝有2个不同的实现, 那么怎么来Autowire⼀个指定的实现? Spring的声明式事务 @Transaction注解⼀般写在什么位置?

技术大牛详谈如何正确使用 Volatile 变量

旧时模样 提交于 2020-04-05 23:05:26
Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”;与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少,但是它所能实现的功能也仅是 synchronized 的一部分。 本文介绍了几种有效使用 volatile 变量的模式,并强调了几种不适合使用 volatile 变量的情形。 锁提供了两种主要特性:互斥(mutual exclusion) 和可见性(visibility)。互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据。 可见性要更加复杂一些,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的 —— 如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题。 Volatile 变量 Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。 Volatile 变量可用于提供线程安全,但是只能应用于非常有限的一组用例:多个变量之间或者某个变量的当前值与修改后值之间没有约束。因此,单独使用 volatile 还不足以实现计数器

Java线程中的锁你掌握了吗?

≡放荡痞女 提交于 2020-04-05 15:46:09
一、同步问题提出 线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏。 例如:两个线程ThreadA、ThreadB都操作同一个对象Foo对象,并修改Foo对象上的数据。 public class Foo { private int x = 100; ​ public int getX() { return x; } ​ public int fix(int y) { x = x - y; return x; } } public class MyRunnable implements Runnable { private Foo foo = new Foo(); ​ public static void main(String[] args) { MyRunnable r = new MyRunnable(); Thread ta = new Thread(r, "Thread-A"); Thread tb = new Thread(r, "Thread-B"); ta.start(); tb.start(); } ​ public void run() { for (int i = 0; i < 3; i++) { this.fix(30); try { Thread.sleep(1); } catch (InterruptedException e) { e

volatile关键字与内存可见性&原子变量与CAS算法

爷,独闯天下 提交于 2020-04-04 11:30:46
1 .volatile 关键字:当多个线程进行操作共享数据时, 可以保证内存中的数据可见 2 .原子变量:jdk1.5后java.util.concurrent.atomic 包下提供常用的原子变量 3 .模拟CAS算法 TestVolatile package com.aff.juc; /* 1.volatile 关键字:当多个线程进行操作共享数据时, 可以保证内存中的数据可见 相较于synchronized是一种较为轻量级的同步策略 注意: volatile不具备"互斥性" 不能保证变量的原子性 */ public class TestVolatile { public static void main(String[] args) { ThreadDemo td = new ThreadDemo(); new Thread(td).start(); while(true){ // synchronized (td) {//同步锁,刷新 效率极低 if(td.isFlag()){ System.out.println("------------"); break; } //} } } } class ThreadDemo implements Runnable { private volatile boolean flag = false; @Override public

java多线程

旧城冷巷雨未停 提交于 2020-04-04 06:16:05
1、进程与线程 我们可以在计算机上运行各种计算机软件程序。每一个运行的程序可能包括多个独立运行的线程(Thread)。 线程(Thread)是一份独立运行的程序,有自己专用的运行栈。线程有可能和其他线程共享一些资源,比如,内存,文件,数据库等。 当多个线程同时读写同一份共享资源的时候,可能会引起冲突。这时候,我们需要引入线程“同步”机制,即各位线程之间要有个先来后到,不能一窝蜂挤上去抢作一团。 同步这个词是从英文synchronize(使同时发生)翻译过来的。我也不明白为什么要用这个很容易引起误解的词。既然大家都这么用,咱们也就只好这么将就。 线程同步的真实意思和字面意思恰好相反。线程同步的真实意思,其实是“排队”:几个线程之间要排队,一个一个对共享资源进行操作,而不是同时进行操作 。 因此,关于线程同步,需要牢牢记住的第一点是: 线程同步就是线程排队 。同步就是排队。线程同步的目的就是避免线程“同步”执行。这可真是个无聊的绕口令。 关于线程同步,需要牢牢记住的第二点是 “共享” 这两个字。 只有共享资源的读写访问才需要同步 。如果不是共享资源,那么就根本没有同步的必要。 关于线程同步,需要牢牢记住的第三点是,只有“ 变量 ”才需要同步访问。如果共享的资源是固定不变的,那么就相当于“常量”,线程同时读取常量也不需要同步。至少一个线程修改共享资源,这样的情况下,线程之间就需要同步。