synchronized

synchronized到底锁住的是谁?

匿名 (未验证) 提交于 2019-12-02 21:40:30
本文代码仓库: https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/sync 先来一道 校招级 并发编程笔试题 题目:利用5个线程并发执行,num数字累计计数到10000,并打印。 1 /** 2 * Description: 3 * 利用5个线程并发执行,num数字累加计数到10000,并打印。 4 * 2019-06-13 5 * Created with OKevin. 6 */ 7 public class Count { 8 private int num = 0; 9 10 public static void main(String[] args) throws InterruptedException { 11 Count count = new Count(); 12 13 Thread thread1 = new Thread(count.new MyThread()); 14 Thread thread2 = new Thread(count.new MyThread()); 15 Thread thread3 = new Thread(count.new MyThread()); 16 Thread thread4 = new Thread(count.new

Java 集合深入理解:Vector

匿名 (未验证) 提交于 2019-12-02 21:40:30
都说Vector和ArrayList相同,只不过Vector是同步的,看下源码 Vector继承结构 public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {...} Vector 和 ArrayList 一样,都是继承自 AbstractList。它是 Stack 的父类。 成员变量 底层实现是数组 protected Object[] elementData; 数组元素个数 protected int elementCount; 扩容时增长数量 protected int capacityIncrement; Vector 的 4 种构造方法 //创建指定容量大小的数组,设置增长量。如果增长量为 非正数,扩容时会扩大两倍 public Vector(int initialCapacity, int capacityIncrement) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new

Java 锁

匿名 (未验证) 提交于 2019-12-02 21:35:18
关于Java 锁的知识整理与回顾(个人笔记): 锁有哪些,分别用来干嘛? Java实现锁有两种方式,synchronized关键字和Lock (1)Lock(可判断锁状态) Lock是基于JDK层面实现。Lock的实现主要有ReentrantLock、ReadLock和WriteLock(引出锁分类:) ①乐观锁/悲观锁: 乐观锁认为读多写少,乐观的认为拿数据时,不会改数据,所以不会上锁,而在更新数据时才会判断有无数据更新。悲观锁悲观的认为,写多,拿数据时先设定数据被修改了,每次在读写数据时都会上锁。 ②公平锁/非公平锁: ReentrantLock在构造函数中提供是否公平锁的初始化方式(默认是非公平锁,就是说可以变成公平锁。即他和synchronized不同之处之一): public ReentrantLock() { sync = new NonfairSync(); } public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); } 非公平锁不按套路出牌,有可能造成“饥饿”现象,但是它的实际执行效率、吞吐量要高于公平锁。 ③独享锁/共享锁 独享锁是指该锁一次只能被一个线程所持有 (ReentrantLock、 Synchronized),共享锁反之

java锁

匿名 (未验证) 提交于 2019-12-02 21:35:18
java锁 1.乐观锁 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,采取在写时先读出当前版本号,然后加锁操作(比较跟上一次的版本号,如果一样则更新),如果失败则要重复读-比较-写的操作。java 中的乐观锁基本都是通过 CAS 操作实现的,CAS 是一种更新的原子操作,比较当前值跟传入值是否一样,一样则更新,否则失败。 2.悲观锁 悲观锁是就是悲观思想,即认为写多,遇到并发写的可能性高,每次去拿数据的时候都认为别人会修改,所以每次在读写数据的时候都会上锁,这样别人想读写这个数据就会 block 直到拿到锁。java中的悲观锁就是Synchronized,AQS框架下的锁则是先尝试cas乐观锁去获取锁,获取不到,才会转换为悲观锁,如 RetreenLock。 3.自旋锁 4.Synchronized同步锁 synchronized 它可以把任意一个非 NULL 的对象当作锁。他属于独占式的悲观锁,同时属于可重入锁。 Synchronized 作用范围 1. 作用于方法时,锁住的是对象的实例(this);2. 当作用于静态方法时,锁住的是Class实例,又因为Class的相关数据存储在永久带PermGen(jdk1.8 则是 metaspace)

Volatile关键字详解

一个人想着一个人 提交于 2019-12-02 20:12:37
简介    在java中,每个线程有一块工作内存区,其中存放这被所有线程共享的主内存中变量值的拷贝。当线程执行时,它在自己的工作内存中操作这些变量。为了获取一个共享变量,一个线程先获取锁定并清除它的工作内存区,这就保证了该共享变量从所有的线程的共享主内存区正确的装入到线程的工作内存区,当线程解锁时保证该工作内存区的变量的值写回到共享主内存区。   线程工作内存和主内存的交互图如下:   从上图中可以看出,主内存和线程工作内存间的数据传输与线程工作内存和线程执行有一定的时间间隔,而且每次所消耗的时间可能还不相同,这样就存在线程操作的数据的不一致性。由于每个线程都有自己的线程工作内存,因此当一个线程改变自己工作内存中的数据的时候,对于其他系统来说可能是不可见的。因此,使用volatile关键字迫使所有的线程均读写主内存中对应的变量,从而使得volatile关键字修饰的变量在多线程间可见。   volatile修饰的变量,jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的。   声明为volatile的变量具有如下特性:   1、其他线程对变量的修改可以即时反映在当前线程中。   2、确保当前线程对volatile变量的修改,能即时的写回到共享主内存中,并被其他线程所见。   3、使用volatile修饰的变量,编译器会保证其有序性。 volatile分析    用在多线程

Synchronized

China☆狼群 提交于 2019-12-02 19:59:29
三种应用方式 修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁 静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁 修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁 字节码指令 javap -v 来查看对应代码的字节码指令,对于同步块的实现使用了monitorenter和monitorexit指令 同一时刻只能有一个线程获取到由synchronized所保护对象的监视器 原理 jdk1.6以后对synchronized锁进行了优化,包含偏向锁、轻量级锁、重量级锁 前提须知: 对象头 对象在内存中的布局分为三块区域:对象头、实例数据和对齐填充 java对象头是实现synchronized的锁对象基础,使用的锁对象存储在java对象头中。 是轻量级锁和偏向锁的关键 Mark Word(标记字) Mark word 用于存储对象自身的运行数据。 哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等等。 Java对象头一般占有两个机器码(在32位虚拟机中,1个机器码等于4字节,也就是32bit) 锁的转换 锁的级别从低到高逐步升级, 无锁->偏向锁->轻量级锁->重量级锁 我们通常说的通过synchronized实现的同步锁,真实名称叫做重量级锁。但是重量级锁会造成线程排队(串行执行)

多线程实现原理

依然范特西╮ 提交于 2019-12-02 19:55:29
JMM保证原子性、可见性、有序性 原子性 两个高级的字节码指令monitorenter和monitorexit,在java中对应的Synchronized来保证代码块内的操作是原子的 可见性 volatile 写操作的时候会多出一个lock前缀的汇编指令 MESI的缓存一致性协议,来保证多CPU下的各个高速缓存中的数据的 一致性 synchronized和final也可以实现可见性 有序性 volatile(禁止指令重排) 遵循as-if-serial语义 synchronized(同一时刻只允许一条线程操作) 内存屏障 通过下面三种方式的作用: 防止指令之间的重排序 保证数据的可见性 写屏障(store barrier) storestore barrier 强制所有在storestore内存屏障之前的所有执行,都要在该内存屏障之前执行,并发送缓存失效的信号 读屏障(load barrier) loadload barrier 强制所有在load barrier读屏障之后的load指令,都在loadbarrier屏障之后执行 全屏障(Full Barrier) 相当于storeload,是一个全能型的屏障 强制了所有在storeload barrier之前的store/load指令,都在该屏障之前被执行,所有在该屏障之后的的store/load指令,都在该屏障之后被执行

面试之java集合

一笑奈何 提交于 2019-12-02 19:52:17
java集合 java集合分类:(普通集合、同步集合、并发集合) 普通集合 Connection接口 List 有序,可重复 ArrayList 优点: 底层数据结构是数组,查询快,增删慢。 缺点: 线程不安全,效率高 LinkedList 优点: 底层数据结构是双向链表,查询慢,增删快。 缺点: 线程不安全,效率高 Vector 优点: 底层数据结构是数组,查询快,增删慢。 缺点: 线程安全,效率低 Set 无序,唯一 HashSet 底层数据结构是哈希表。(无序,唯一) 如何来保证元素唯一性? 1.依赖两个方法:hashCode()和equals() LinkedHashSet 底层数据结构是链表和哈希表。(FIFO插入有序,唯一) 1.由链表保证元素有序 2.由哈希表保证元素唯一 TreeSet 底层数据结构是红黑树。(唯一,有序) Map接口(key-value 的键值对,key 不允许重复,value 可重复,重复时会覆盖前一个key) Map中的key:无序的、不可重复的,value:无序的、可重复的 HashMap:无序的,效率高,但不是线程安全的,key和value都允许为null。 TreeMap:有序的,底层使用红黑树,保证按照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序。 LinkedHashMap

JAVA对象方法-wait

大城市里の小女人 提交于 2019-12-02 19:32:02
最简单的东西,往往包含了最复杂的实现,因为需要为上层的存在提供一个稳定的基础,Object作为java中所有对象的基类,其存在的价值不言而喻,其中wait和notify方法的实现多线程协作提供了保证。 案例 public class WaitTestDemo { public static void main(String[] args) { Message msg = new Message("process it"); Waiter waiter = new Waiter(msg); new Thread(waiter,"waiterThread").start(); Waiter waiter1 = new Waiter(msg); new Thread(waiter1, "waiter1Thread").start(); Notifier notifier = new Notifier(msg); new Thread(notifier, "notifierThread").start(); System.out.println("All the threads are started"); } public static class Message { private String msg; public Message(String str){ this.msg=str

synchronized:内部锁

折月煮酒 提交于 2019-12-02 19:14:52
synchronized:内部锁 起源: 并行程序开发涉及多线程、多任务间的协作和数据共享 一)、内部锁:synchronized 1).定义在方法上 public synchronized void method() 当method方法被调用时,调用线程必须获得当前对象的锁。 锁对象:当前对象。 2).同步代码块 synchronized(Object obj){ } 锁对象:自定义一个共同使用的锁对象。 好处: 1.同步块可以更为精确的控制同步代码范围 2.小的代码块非常有利于锁的快进快出,假设同步块前后代码段较为耗时,而它 ​ 们又无需进行同步操作,那么,将这些代码纳入整个同步代码块就会增加锁的等 ​ 待时间。 3).静态方法的同步 public synchronized static method() 锁对象:Class对象 4).使用wait()、notify()来创建一个阻塞队列 构建: 方法一:当队列有数据时,取出第一个元素,没有数据时,线程进入等待状态,线 ​ 程被阻塞。 方法二:将一个对象添加进入队列,并通知等待的方法。 使用wait()、notify()实现了多线程之间的协作以及数据的共享。 模拟队列: /** * 使用synchronize和wait(), notify()实现一个阻塞队列 * 实现: * 获取队列中的元素: 使用pop操作队列,当队列中有元素