线程安全

JVM学习(八):线程安全

亡梦爱人 提交于 2019-11-28 12:25:59
1、 线程安全 :当 多个线程访问一个对象 时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也 无需进行额外的同步 ,或者在调用方进行任何其他的协调操作,调用这个对象的行为都 可以获得正确的结果 ,那这个对象就是线程安全的。 2、线程安全的等级(由强到弱依次如下): (1) 不可变 :不可变( Immutable )对象一定是线程安全的。如用 final 修饰的基本数据类型、 String 、 枚举类 以及java.lang. Number 的部分子类( Long 、 Double 等包装类,但AtomicInteger和AtomicLong并非不可变)。 (2) 绝对线程安全 :Java API中标注自己是线程安全的类,大多数都不是绝对线程安全。比如Vector容器,在同时做删除元素和获取元素的操作时,需要额外进行同步处理,才能真正做到线程安全。 (3) 相对线程安全 :即我们通常意义上所讲的线程安全,它需要保证对这个对象 单独的操作是线程安全的 ,但对于一些 特定顺序的连续调用 ,需要使用额外的同步措施才能保证调用结果的正确性。Java中比如Vector、HashTable、Collections的synchronizedCollection()方法包装的集合等都属于相对线程安全。 (4) 线程兼容 :对象本身不是线程安全,需要额外的同步手段来保证并发执行的安全

HashMap和Hashtable的区别

南楼画角 提交于 2019-11-28 12:16:28
HashMap和Hashtable的比较是Java面试中的常见问题,用来考验程序员是否能够正确使用集合类以及是否可以随机应变使用多种思路解决问题。HashMap的工作原理、ArrayList与Vector的比较以及这个问题是有关Java 集合框架的最经典的问题。Hashtable是个过时的集合类,存在于Java API中很久了。在Java 4中被重写了,实现了Map接口,所以自此以后也成了Java集合框架中的一部分。Hashtable和HashMap在Java面试中相当容易被问到,甚至成为了集合框架面试题中最常被考的问题,所以在参加任何Java面试之前,都不要忘了准备这一题。 这篇文章中,我们不仅将会看到HashMap和Hashtable的区别,还将看到它们之间的相似之处。 HashMap和Hashtable的区别 HashMap和Hashtable都实现了Map接口,但决定用哪一个之前先要弄清楚它们之间的分别。主要的区别有:线程安全性,同步(synchronization),以及速度。 HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。 HashMap是非synchronized

Web系统大规模并发:电商秒杀与抢购

烈酒焚心 提交于 2019-11-28 11:28:27
一、大规模并发带来的挑战 在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个Web系统遇到了很多的问题和挑战。如果Web系统不做针对性的优化,会轻而易举地陷入到异常状态。我们现在一起来讨论下,优化的思路和方法哈。 1. 请求接口的合理设计 一个秒杀或者抢购页面,通常分为2个部分,一个是静态的HTML等内容,另一个就是参与秒杀的Web后台请求接口。 通常静态HTML等内容,是通过CDN的部署,一般压力不大,核心瓶颈实际上在后台请求接口上。这个后端接口,必须能够支持高并发请求,同时,非常 重要的一点,必须尽可能“快”,在最短的时间里返回用户的请求结果。为了实现尽可能快这一点,接口的后端存储使用内存级别的操作会更好一点。仍然直接面向 MySQL之类的存储是不合适的,如果有这种复杂业务的需求,都建议采用异步写入。 当然,也有一些秒杀和抢购采用“滞后反馈”,就是说秒杀当下不知道结果,一段时间后才可以从页面中看到用户是否秒杀成功。但是,这种属于“偷懒”行为,同时给用户的体验也不好,容易被用户认为是“暗箱操作”。 2. 高并发的挑战:一定要“快” 我们通常衡量一个Web系统的吞吐率的指标是QPS(Query Per Second,每秒处理请求数),解决每秒数万次的高并发场景,这个指标非常关键。举个例子,我们假设处理一个业务请求平均响应时间为100ms,同时,

Java Stack解析

南笙酒味 提交于 2019-11-28 11:01:33
Stack继承自Vector 虽然Stack的可以由Vector封装实现,且底层数据结构都是数组。但是为什么Stack作为一个基础的数据结构,没有像List、Queue以接口的形式继承自Collection,而是Vector的一个子类,个人认为这个逻辑性不是很合理。 Stack是一个线程安全的类,不仅仅由于它的基类是线程安全的,它的子类方法也都是同步方法。为什么Stack需要是线程安全的?这一点我也不理解 Stack的API: 1.push() 入栈 2.pop() 出栈 3.peek() 返回栈顶元素,不出栈 4.empty() 是否为空 为什么不叫isEmpty()呢?父类已存在该方法。两者只是实现上前者利用了Vector的封装方法size(),后者直接判断元素个数,不理解empty()方法的存在意义。 5.search() 从栈顶元素向下,循环该元素第一次出现的位置 Stack的数据结构、API很容易理解,但是JDK里对Stack的实现却让人很费解,网上的讨论多认为这是早期设计不规范所致 来源: https://www.cnblogs.com/elinlinlinlog/p/11405940.html

Spring单例与线程安全小结

时光毁灭记忆、已成空白 提交于 2019-11-28 10:32:34
一、Spring单例模式与线程安全 Spring框架里的bean,或者说组件,获取实例的时候都是默认的单例模式,这是在多线程开发的时候要尤其注意的地方。 单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。 当多用户同时请求一个服务时,容器会给每一个请求分配一个线程,这是多个线程会并发执行该请求多对应的业务逻辑(成员方法),此时就要注意了,如果该处理逻辑中有对该单列状态的修改(体现为该单列的成员属性),则必须考虑线程同步问题 同步机制的比较  ThreadLocal和线程同步机制相比有什么优势呢?ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。   在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。   而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时

java并发之线程安全问题

强颜欢笑 提交于 2019-11-28 10:20:05
并发(concurrency)一个并不陌生的词,简单来说,就是cpu在同一时刻执行多个任务。 而Java并发则由多线程实现的。 在jvm的世界里,线程就像不相干的平行空间,串行在虚拟机中。(当然这是比较笼统的说法,线程之间是可以交互的,他们也不一定是串行。) 多线程的存在就是压榨cpu,提高程序性能,还能减少一定的设计复杂度(用现实的时间思维设计程序)。 多线程会引出很多难以避免的问题, 如死锁,脏数据,线程管理的额外开销,等等。更大大增加了程序设计的复杂度。 死锁 和 脏数据 就是典型的 线程安全 问题。 简单来说,线程安全就是: 在多线程环境中,能永远保证程序的正确性。 只有存在 共享数据 时才需要考虑线程安全问题。 解决线程安全问题: 如何解决的确是该流程的重点。目前分三种方式解决: 第一种,修改线程模型。即不在线程之间共享该状态变量。一般这个改动比较大,需要量力而行。 第二种,将对象变为不可变对象。有时候实现不了。 第三种,就比较通用了,在访问状态变量时使用同步。 synchronized和Lock都可以实现同步。简单点说,就是在你修改或访问可变状态时加锁,独占对象,让其他线程进不来。 这也算是一种线程隔离的办法。(这种方式也有不少缺点,比如说死锁,性能问题等等) 其实有一种更好的办法,就是设计线程安全类。《代码大全》就有提过,问题解决得越早,花费的代价就越小。 是的

java面试题(非原创)

情到浓时终转凉″ 提交于 2019-11-28 10:08:40
一、开场白 简单的介绍一下自己的工作经历与职责,在校或者工作中主要的工作内容,主要负责的内容;(你的信息一清二白的写在简历上,能答出来的最好写在上面,模棱两可不是很清楚的最好不要写,否则会被问的很尴尬) 介绍下自己最满意的,有技术亮点的项目或平台,重点介绍下自己负责那部分的技术细节;(主要对自己做过的事情是否有清晰的描述) 二、Java基础 什么是字符串常量池? String为什么是不可变的? String s = new String("xyz");究竟产生了几个对象,从JVM角度谈谈? String拼接字符串效率低,你知道原因吗? 你真的了解String的常见API吗? Java中的subString()真的会引起内存泄露么? 浅析Java中的final关键字? 浅析Java中的static关键字? 你对Java中的volatile关键字了解多少? i++是线程安全的吗?如何解决线程安全性? 从字节码角度深度解析 i++ 和 ++i 线程安全性原理? 请谈谈什么是CAS? 从源码角度看看ArrayList的实现原理? 手写LinkedList的实现,彻底搞清楚什么是链表? Java中方法参数的传递规则? Java中throw和throws的区别是什么? 重载和重写的区别? 手写ArrayList的实现,在笔试中如何过关斩将? finally语句块你踩过哪些坑?

Java并发专题(二)线程安全

一个人想着一个人 提交于 2019-11-28 08:52:33
前言   随着时代的发展,CPU核数的增加和计算速度的提升,串行化的任务执行显然是对资源的极大浪费,掌握多线程是每个程序员必须掌握的技巧。但是同时多线程也是一把双刃剑,带来了共享资源安全的隐患。在本节会介绍线程安全是什么、最基本的独占悲观式来保证线程安全的介绍。随着章节步步深入。 1.1 什么是线程安全? 1.1.1 初识线程安全的尴尬   本人是17年毕业的,刚进第一家公司的时候没有开发经验,对接第三方支付公司外部API压测的时候碰到一个问题:对方要求我5次/s,一共发300s的付款请求。其中一个请求的id,保证当日每一次唯一。我请求的id从1开始递增,但是总是也达不到300*5=1500。也闹出了很尴尬的笑话。这是我第一次接触多线程。为了简化问题,例子如下:2个线程对一个数字递增加2000次,看看是否最后是2000。 /** * 多线程递增某一个数字的测试类。 * * @author GrimMjx */ public class UnsafeAdd { private int i; public int getNext() { return i++; } public static void main(String[] args) throws InterruptedException { UnsafeAdd multiAdd = new UnsafeAdd();

单例模式正确使用方式

。_饼干妹妹 提交于 2019-11-28 08:45:33
这次分享我们就来谈谈单例模式的使用,其实在本公众号设计模式的第一篇分享就是单例模式,为什么又要讨论单例模式了?主要是那篇文章谈的比较浅,只对单例模式的主要思想做了一个分享,这篇文章会从多个方面去分享单例模式的使用,下面进入正题。 使用Java做程序的小伙伴都知道单例,尤其是使用spring框架做项目的,大家都知道spring框架管理类默认都是单例模式的,并且是线程安全的。那么如果保证一个类只被初始化一次且线程安全了?带着这个问题我们开始这篇文章。 在刚接触设计模式的时候,大多数人首先接触到的第一个设计模式就是单例模式,当然大多数人都只停留在单例模式,在平时的开发中用的少之又少,这篇文章会帮助大家从多个方面理解单例模式,此文代码较多,如果对单例模式概念不是很清楚的小伙伴可以看另一篇文章《设计模式之单例模式》。 1. 懒汉模式 package com.study.concurrency.base_concurrency.example.singleton; /** * <p>Title: Singleton01</p > * <p>Description: 懒汉模式 单例实例在第一次使用时进行创建 </p > * <p>Company: http://www.yinjiedu.com</p > * <p>Project: concurrency</p > * * @author:

Java Vector解析与ArrayList区别

試著忘記壹切 提交于 2019-11-28 08:45:17
Vector继承了AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable,和ArrayList一致 Vector大致与ArrayList一致,但是有以下几点区别 1 初始化 默认无参构造方法 Vector会初始化一个长度为10的数组,ArrayList在具体调用时再创建数组。 比较之下,ArrayList延迟化加载更节省空间 2 扩容 (grow()) Vector当增量为0时,扩充为原来大小的2倍,当增量大于0时,扩充为原来大小加增量 ArrayList扩充算法:原来数组大小加原来数组的一半 为什么Vector选择了较为浪费空间的方式扩容,我相信C++ Vector和Java Vector的该处原理应该一致, https://www.zhihu.com/question/36538542/answer/67929747 3 线程安全 Vector是线程安全的,ArrayList是非线程安全的 Vector的线程安全包括其内部类如迭代器实现类ListItr 其实最大的区别就是线程安全性,当然如果我们想创建一个线程安全的ArrayList,可以调用Collections.synchronizedList(),得到静态内部类SynchronizedList,利用同步代码块处理ArrayList。