synchronized

synchronized关键字的可重入性

泄露秘密 提交于 2019-12-01 22:01:48
/**父类*/public class SynchronizedDemo1 implements Runnable { @Override public void run() { try { method(); } catch (InterruptedException e) { e.printStackTrace(); } } public void method() throws InterruptedException { synchronized(SynchronizedDemo1.class) { System.out.println(Thread.currentThread().getName() + " super start"); Thread.sleep(3000); System.out.println(Thread.currentThread().getName() + " super finished"); } }}//子类,在子类的main方法中调用子类的synchronized方法,在method方法中调用父类的method方法,是可以执行父类的method方法的,也就是说对于一个锁对象而言,这是传递过去的,也即在这个线程中这个锁是可以重复利用的,那么如果锁都不是同一个对象的话,自然也就不存在什么同步了(一开始没反应过来)class Son

Synchronized与Lock

纵饮孤独 提交于 2019-12-01 21:37:58
Synchronized是并发中使用最频繁的关键字了,它可以使用在方法、代码块上,表示对该段代码加锁,而必须要持有锁才能执行这段代码。Synchronized具有互斥性。 说起来蛮简单,而实际中编程 ,最难得地方有两点 1、确定并发间隙 2、确定锁的对象 做好这两点才能处理好锁的粒度,是并发的性能更好。 eg1、Synchronized加在静态方法上,不同的线程调用这两个方法互斥。此时synchronize锁的是该类 public class SynchronizeDemo1 { public synchronized static void fool1() throws Exception{ System.out.println("fool1...开始"); Thread.sleep(10000L); System.out.println("fool1...结束"); } public synchronized static void fool2() throws Exception{ System.out.println("fool2...开始"); Thread.sleep(5000L); System.out.println("fool2...结束"); } public static void main(String args[]){ new Thread(new

各种同步方法性能比较(synchronized,ReentrantLock,Atomic)

只谈情不闲聊 提交于 2019-12-01 21:37:44
5.0的多线程任务包对于同步的性能方面有了很大的改进,在原有synchronized关键字的基础上,又增加了ReentrantLock,以及各种Atomic类。了解其性能的优劣程度,有助与我们在特定的情形下做出正确的选择。 总体的结论先摆出来: synchronized: 在资源竞争不是很激烈的情况下,偶尔会有同步的情形下,synchronized是很合适的。原因在于,编译程序通常会尽可能的进行优化synchronize,另外可读性非常好,不管用没用过5.0多线程包的程序员都能理解。 ReentrantLock: ReentrantLock提供了多样化的同步,比如有时间限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在资源竞争不激烈的情形下,性能稍微比synchronized差点点。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而ReentrantLock确还能维持常态。 Atomic: 和上面的类似,不激烈情况下,性能比synchronized略逊,而激烈的时候,也能维持常态。激烈的时候,Atomic的性能会优于ReentrantLock一倍左右。但是其有一个缺点,就是只能同步一个值,一段代码中只能出现一个Atomic的变量,多于一个同步无效。因为他不能在多个Atomic之间同步。 所以

CAS原理 Java SE1.6中的Synchronized

Deadly 提交于 2019-12-01 20:24:50
在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁(后面的章节还会谈到锁)。 锁机制存在以下问题: (1)在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题。 (2)一个线程持有锁会导致其它所有需要此锁的线程挂起。 (3)如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能风险。 volatile是不错的机制,但是volatile不能保证原子性。因此对于同步最终还是要回到锁机制上来。 独占锁是一种悲观锁,synchronized就是一种独占锁 ,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁。而另一个更加有效的锁就是乐观锁。所谓 乐观锁就是, 每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。 CAS 操作 上面的乐观锁用到的机制就是CAS,Compare and Swap。 CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。 非阻塞算法 (nonblocking algorithms) 一个线程的失败或者挂起不应该影响其他线程的失败或挂起的算法。 现代的CPU提供了特殊的指令,可以自动更新共享数据,而且能够检测到其他线程的干扰,而 compareAndSet()

HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别

纵然是瞬间 提交于 2019-12-01 19:30:50
HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别 ①HashMap的工作原理 HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,让后找到bucket位置来储存值对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会储存在链表的下一个节点中。 HashMap在每个链表节点中储存键值对对象。 当两个不同的键对象的hashcode相同时会发生什么? 它们会储存在同一个bucket位置的链表中。键对象的equals()方法用来找到键值对。 因为HashMap的好处非常多,我曾经在电子商务的应用中使用HashMap作为缓存。因为金融领域非常多的运用Java,也出于性能的考虑,我们会经常用到HashMap和ConcurrentHashMap。 ②HashMap和Hashtable的区别 HashMap和Hashtable都实现了Map接口,但决定用哪一个之前先要弄清楚它们之间的分别。主要的区别有:线程安全性,同步(synchronization),以及速度。 HashMap几乎可以等价于Hashtable

线程同步 synchronized

时间秒杀一切 提交于 2019-12-01 19:22:17
1、了解 synchronized 在Java中,每一个对象都拥有一个锁标记(monitor),也称为监视器,多线程同时访问某个对象时,线程只有获取了该对象的锁才能访问,这个锁可通过为方法添加关键字 synchronized 来获得,来保证同一对象在同一 时间只有同一线程在访问,只有等待这个方法执行完毕或者代码块执行完毕,这个线程才会释放该对象的锁,其他线程才能执行这个方法或者代码块。 2、synchronized的特点 (1)对于synchronized方法或者synchronized代码块,当出现异常时,JVM会自动释放当前线程占用的锁,因此不会由于异常导致出现死锁现象 (2)使用synchronized时,等待的线程会一直等待下去,不能够响应中断; (3)通过synchronized无法知道有没有成功获取锁。 3、三种使用方式 (1)修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁 public synchronized void increase(){   i++; } 对于当前类的对象加锁,不同对象有不同的锁,针对同一线程访问的加锁;若是两个对象,则两个对象获取不同的锁,两个线程可以同时进入该方法,以上代码的加锁就会出现线程不安全 (2)修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁 public static

【Java并发编程之深入理解】Synchronized的使用

痴心易碎 提交于 2019-12-01 18:57:35
1.为什么要使用synchronized 在并发编程中存在线程安全问题,主要原因有:1.存在共享数据 2.多线程共同操作共享数据。关键字synchronized可以保证在同一时刻,只有一个线程可以执行某个方法或某个代码块,同时synchronized可以保证一个线程的变化可见(可见性),即可以代替volatile。 2.实现原理 synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性 3.synchronized的三种应用方式 Java中每一个对象都可以作为锁,这是synchronized实现同步的基础: 普通同步方法(实例方法),锁是当前实例对象 ,进入同步代码前要获得当前实例的锁 静态同步方法,锁是当前类的class对象 ,进入同步代码前要获得当前类对象的锁 同步方法块,锁是括号里面的对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。 4.synchronized的作用 Synchronized是Java中解决并发问题的一种最常用最简单的方法 ,他可以确保线程互斥的访问同步代码 来源: https://www.cnblogs.com/yachao1120/p/11713216.html

Java并发编程之多线程同步

十年热恋 提交于 2019-12-01 18:48:24
线程安全就是防止某个对象或者值在多个线程中被修改而导致的数据不一致问题,因此我们就需要通过同步机制保证在同一时刻只有一个线程能够访问到该对象或数据,修改数据完毕之后,再将最新数据同步到主存中,使得其他线程都能够得到这个最新数据。下面我们就来了解Java一些基本的同步机制。 Java提供了一种稍弱的同步机制即volatile变量,用来确保将变量的更新操作通知到其他线程。当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的。然而,在访问volatile变量时不会执行加锁操作,因此也就不会使线程阻塞,因此volatile变量是一种比synchronized关键字更轻量级的同步机制。 volatile变量对所有的线程都是可见的,对volatile变量所有的写操作都能立即反应到其他线程之中,即volatile变量在各个线程中是一致的。 有一种情况需要注意:volatile的语义不能确保递增(count++)的原子性,除非你能确保只有一个线程对变量执行写操作。 123456789101112131415161718192021222324252627282930313233 public class VolatileTest{ public static volatile int i; public static void increase(){ i++; }

设计模式之单例模式

心不动则不痛 提交于 2019-12-01 18:45:20
参考资料: 老司机来教你单例的正确姿势 《Android源码设计模式解析与实战》 单例模式可以说是应用最广泛的模式了, 面试也经常被问到, 经常会被要求能够手写单例, 所以我今天也来总结一下 单例模式的定义 确保某一个类只有一个实例, 并且自定实例化并向整个系统提供这个实例 单例模式的使用场景 确保某个类有且只有一个对象的场景, 避免产生多个对象消耗过多的资源, 或者某种类型的对象只应该有且只有一个.例如, 创建一个对象需要消耗的资源过多, 如要访问IO和数据库等资源 单例的UML类图 插点题外话说一下怎么看UML类图, 例如这里的Singleton矩形框就代表一个类, 第一层显示类的名称, 抽象类用斜体表示; 第二层是类的特性, 通常是字段和属性; 第三层是类的操作, 通常是方法. ‘+’表示public, ‘-‘表示private, ‘#’表示protected, 例如这里的getInstance()方法是public的, 构造方法是private的. 与类图有区别的是接口图, 顶端有 <<interface>> 显示 实现单例模式有一下几个关键点: 构造函数不对外开放, 一般为private, 是的客户端不能通过new的形式手动构造单例类的对象 通过一个静态方法或者枚举返回单例类对象 在多线程环境中也需要确保单例类的对象有且只有一个 确保单例类对象在反序列化时不会重新构建对象

synchronized底层实现原理

不羁的心 提交于 2019-12-01 18:39:08
基于进入和退出管程(Monitor)对象实现,无论显式(Monitorenter Monitorexit)还是隐式都是如此。同步方法并不是由monitorenter和monitorexit指令来实现同步的,而是由方法调用指令读取运行时常量池中的ACC_SYNCHRONIZED标志来隐式实现的。 在JVM中,对象在内存中的布局分为三块区域:对象头、实例数据和对齐填充。 实例变量:存放类的属性数据信息,包括父类的属性信息,如果是数组的实例部分还包括数组的长度,这部分内存按4字节对齐。 填充数据:由于虚拟机要求对象起始地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅是为了字节对齐,这点了解即可 而对于顶部,则是Java头对象,它实现synchronized的锁对象的基础,这点我们重点分析它,一般而言,synchronized使用的锁对象是存储在Java对象头里的,jvm中采用2个字来存储对象头(如果对象是数组则会分配3个字,多出来的1个字记录的是数组长度),其主要结构是由Mark Word 和 Class Metadata Address 组成 虚拟机位数 头对象结构 说明 32/64bit Mark Word 存储对象的hashCode、锁信息或分代年龄或GC标志等信息 32/64bit Class Metadata Address 类型指针指向对象的类元数据