synchronized

使用同步方法而不是同步块是否有优势?

↘锁芯ラ 提交于 2020-02-26 22:06:59
有谁能举例说明同步方法优于同步块的优势吗? #1楼 可以使用反射API检查同步方法。 这对于测试某些合同可能很有用,例如 模型中的所有方法都已同步 。 以下代码段显示了Hashtable的所有同步方法: for (Method m : Hashtable.class.getMethods()) { if (Modifier.isSynchronized(m.getModifiers())) { System.out.println(m); } } #2楼 与线程同步。 1)永远不要在线程中使用synced(this),这是行不通的。 与(this)同步使用当前线程作为锁定线程对象。 由于每个线程都独立于其他线程,因此没有同步协调。 2)代码测试表明,在Mac上的Java 1.6中,方法同步不起作用。 3)Synchronized(lockObj),其中lockObj是在其上同步的所有线程的公共共享对象。 4)ReenterantLock.lock()和.unlock()工作。 参见Java教程。 以下代码显示了这些要点。 它还包含将替换ArrayList的线程安全Vector,以表明添加到Vector的许多线程不会丢失任何信息,而与ArrayList相同的线程可能会丢失信息。 0)当前代码显示由于竞争条件而导致的信息丢失A)注释当前标记为A的行,并取消注释其上方的A行,然后运行

hashmap与currentHashMap

时间秒杀一切 提交于 2020-02-26 18:39:10
hashmap的缺点 多线程不安全,在并发场景下使用时容易出现死循环,脏读问题等 死循环: https://juejin.im/post/5a66a08d5188253dc3321da0 (这篇好点) https://blog.csdn.net/justloveyou_/article/details/72783008 脏读: https://blog.csdn.net/qq_33591903/article/details/81672260 currrntHashMap的改进 由于扩容是按照2的幂次方进行的,所以扩展前在同一个桶中的元素,现在要么还是在原来的序号的桶里,或者就是原来的序号再加上一个2的幂次方,就这两种选择。 其中抛弃了JDK1.7的 Segment 分段锁,而采用了 CAS + synchronized 来保证并发安全性。 CAS与synchronized : https://juejin.im/post/5c37377351882525ec200f9e CAS(乐观锁)比synchronized(悲观锁)轻量级一点,消耗的资源比较小。 CAS 是 compare and swap 的简写,即比较并交换。它是指一种操作机制,而不是某个具体的类或方法。在 Java 平台上对这种操作进行了包装。在 Unsafe 类中,调用代码如下: unsafe

线程安全性原子性、可见性、有序性

怎甘沉沦 提交于 2020-02-26 14:52:15
原子性----锁(synchronized) jdk提供锁主要分两种: 1、synchionized:依赖JVM,java关键字,作用对象的作用范围内 修饰代码块:大括号括起来的代码,作用于调用的对象,当被修饰的代码和修饰的方法一样时,那么修饰代码块和修饰方法是等同的 public void test1 ( ) { synchronized ( this ) { for ( int i = 0 ; i < 1 来源: CSDN 作者: 大军465 链接: https://blog.csdn.net/u013449046/article/details/104513068

【笔记】并发

拜拜、爱过 提交于 2020-02-26 07:39:48
一篇文章带你解析,乐观锁与悲观锁的优缺点 乐观锁与悲观锁 乐观锁与悲观锁不是指具体的什么类型的锁,而是指看待并发同步的角度。 定义 适用场景 使用 优缺点 悲观锁 悲观的认为,不加锁的并发操作一定会出问题。 写操作非常多 就是利用各种锁(synchronized独占锁) 保证数据安全 使用synchronized同步锁进行线程阻塞和唤醒切换以及用户态内核态间的切换操作额外浪费消耗cpu资源 乐观锁 认为对于同一个数据的并发操作,是不会发生修改的。 读操作非常多 无锁编程,采用的是CAS算法,典型的例子就是原子类,通过CAS自旋实现原子操作的更新。 不加锁会带来大量的性能提升。 冲突多时,自旋消耗大 在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题。 (2)一个线程持有锁会导致其它所有需要此锁的线程挂起。 (3)如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能风险。 CAS 定义 CAS,compare and swap的缩写,比较并交换。 CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。有效地说明了“我认为位置 V 应该包含值 A;如果包含该值,则将 B 放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。 存在的问题 ABA问题。 但是如果一个值原来是A,变成了B,又变成了A

🔥史上最全的Java并发系列之Java并发机制的底层实现原理

社会主义新天地 提交于 2020-02-26 05:10:55
并发编程的3个基本概念 原子性 定义: 即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。 原子性是拒绝多线程操作的,不论是多核还是单核,具有原子性的量,同一时刻只能有一个线程来对它进行操作。简而言之,在整个操作过程中不会被线程调度器中断的操作,都可认为是原子性。例如 a=1是原子性操作,但是a++和a +=1就不是原子性操作。Java中的原子性操作包括: a. 基本类型的读取和赋值操作,且赋值必须是数字赋值给变量,变量之间的相互赋值不是原子性操作。 b.所有引用reference的赋值操作 c.java.concurrent.Atomic.* 包中所有类的一切操作 可见性 定义:指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。 在多线程环境下,一个线程对共享变量的操作对其他线程是不可见的。Java提供了volatile来保证可见性,当一个变量被volatile修饰后,表示着线程本地内存无效,当一个线程修改共享变量后他会立即被更新到主内存中,其他线程读取共享变量时,会直接从主内存中读取。当然,synchronize和Lock都可以保证可见性。synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性。 有序性 定义

HashMap,Hashtable,ConcurrentHashMap 和 synchronized Map 的原理和区别

ぐ巨炮叔叔 提交于 2020-02-26 00:00:26
HashMap 是否是线程安全的,如何在线程安全的前提下使用 HashMap,其实也就是 HashMap , Hashtable , ConcurrentHashMap 和 synchronized Map 的原理和区别。当时有些紧张只是简单说了下HashMap不是线程安全的;Hashtable 线程安全,但效率低,因为是 Hashtable 是使用 synchronized 的,所有线程竞争同一把锁;而 ConcurrentHashMap 不仅线程安全而且效率高,因为它包含一个 segment 数组,将数据分段存储,给每一段数据配一把锁,也就是所谓的锁分段技术。当时忘记了 synchronized Map 和解释一下 HashMap 为什么线程不安全。面试结束后问了下面试官哪里有些不足,面试官说上面这个问题的回答算过关,但可以在深入一些或者自己动手尝试一下。so~~~虽然拿到了 offer,但还是再整理一下,不能得过且过啊。 为什么HashMap是线程不安全的 总说 HashMap 是线程不安全的,不安全的,不安全的,那么到底为什么它是线程不安全的呢?要回答这个问题就要先来简单了解一下 HashMap 源码中的使用的 存储结构 (这里引用的是 Java 8 的源码,与7是不一样的)和它的 扩容机制 。 HashMap的内部存储结构 下面是 HashMap 使用的存储结构: 1 2

单例模式

戏子无情 提交于 2020-02-25 19:27:00
1.单例模式 保证一个类仅有一个实例。 (1)实现方式 1、懒汉模式(线程不安全) 2、懒汉模式(线程安全) 3、饿汉模式(线程安全) 4、静态类内部加载(线程安全) 5、枚举方法(线程安全) 6、双重校验锁法(通常线程安全,低概率不安全) 7、带 volatile 的双重校验锁法(线程安全) 8、使用 ThreadLocal 实现单例模式(线程安全) 9、使用 CAS 锁实现(线程安全) … 实际还有各种奇淫技巧,不只只 9 种方式。 单例模式的安全方式 单例模式大家并不陌生,也都知道它分为什么懒汉式、饿汉式之类的。但是你对单例模式的理解足够透彻吗?今天我带大家一起来看看我眼中的单例,可能会跟你的认识有所不同。 下面是一个简单的小实例: [java] view plaincopyprint? 1. //简单懒汉式 2. public class Singleton { 3. 4. //单例实例变量 5. private static Singleton instance = null; 6. 7. //私有化的构造方法,保证外部的类不能通过构造器来实例化 8. private Singleton() {} 9. 10. //获取单例对象实例 11. public static Singleton getInstance() { 12. 13. if (instance ==

锁的升级打怪:通俗易懂讲解偏向锁、轻量级锁和重量级锁

青春壹個敷衍的年華 提交于 2020-02-25 14:43:57
PART0: PART1: 首先通过一个小例子来解释一下三种锁的区别: 假如家里只有一个碗,当我自己在家时,没有人会和我争碗,这时即为偏向锁状态 当我和女朋友都在家吃饭时,如果女朋友不是很饿,则她会等我吃完再用我的碗去吃饭,这就是轻量级锁状态 当我和女朋友都很饿的时候,这时候就会去争抢这唯一的一个碗(贫穷的我)吃饭,这就是重量级锁状态 PART2: 我是一个线程,生活在JVM(Java虚拟机)中, 这一段日子过得有些无聊,整个世界似乎只有这一个人,天天忙着执行代码,想休息一下都很难。 我听说人类写的代码中有些特殊的地方,叫做 临界区 ,比如synchronized修饰的方法或者代码块,他们非常神奇,在同一时刻JVM老大只允许一个线程进入执行。 实际上,老大设置了一把锁,抢到了这把锁就可以执行,否则只能阻塞,等待别人释放锁。 老大说,阻塞就是不用干活了,老老实实地等着就行。 竟然还有这等美事! 赶紧让我阻塞一次吧。 可是老大又说:“每次设置锁我都得和操作系统打交道,请他在内核中维护一个什么Mutex(互斥量)的东西,他还得把你们这些线程阻塞,切换,这可是一笔巨大的费用啊,所以这些锁还是少用为妙。” 我运气也不好,我不知道执行了多少代码,调用了多少函数,竟然一次也没遇到临界区! 我想也许这个程序员编程时不小心,没有考虑多线程并发的情况; 也有可能是这些程序大部分都是无状态的

小白日记

*爱你&永不变心* 提交于 2020-02-25 14:33:49
String,StringBuffer,StringBulider的区别 String是只读字符串,每次改变都需要创建新的对象; StringBulider和StringBuffer表示的字符串对象可以直接修改,无需创建新的对象。这样在效率上就会有所提升。当需要对字符串进行大量操作时,建议使用这两种。 而StringBulider和StringBuffer又有什么区别呢? StringBuffer的所有的公开方法都是用synchronized修饰的,所以他的线程是安全的。StringBulider则没有用synchronized修饰,所以是是不安全的。也是因为StringBuffer加了锁,导致性能方面肯定是不如StringBulider的。 单线程的建议使用StringBulider,多线程建议使用StringBuffer。 来源: CSDN 作者: weixin_45401536 链接: https://blog.csdn.net/weixin_45401536/article/details/104494524

Java基础常见面试题最后十题

两盒软妹~` 提交于 2020-02-24 20:15:48
1.为什么等待(wait())和通知(notify())是在 Object 类而不是 Thread 中声明的? 生产者-消费者问题代码实现 ①.生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。 ②.解决办法:要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题,常用的方法有信号灯法等。如果解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者和消费者的情形。 void notify() 唤醒在此对象监视器上等待的单个线程 void notifyAll()