简栈文化

Java技术人的成长之路~


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

CAS原理分析及ABA问题详解

发表于 2020-02-15 | 更新于: 2020-08-02 | 分类于 Java
什么是CASCAS即Compare And Swap的缩写,翻译成中文就是比较并交换,其作用是让CPU比较内存中某个值是否和预期的值相同,如果相同则将这个值更新为新值,不相同则不做更新,也就是CAS是原子性的操作(读和写两者同时具有原子性),其实现方式是通过借助C/C++调用CPU指令完成的,所以效率很高。CAS的原理很简单,这里使用一段Java代码来描述 123456789public boolean compareAndSwap(int value, int expect, int update) {// 如果内存中的值value和期望值expect一样 则将值更新为新值update if (value == expect) { value = update; return true; } else { return false; }} 大致过程是将内存中的值、我们的期望值、新值交给CPU进行运算,如果内存中的值和我们的期望值相同则将值更新为新值, ...
阅读全文 »

ArrayList与CopyOnWriteArrayList常见操作与问题

发表于 2020-02-14 | 更新于: 2020-08-02 | 分类于 Java
ArrayList循环遍历并删除元素的常见陷阱在工作和学习中,经常碰到删除ArrayList里面的某个元素,看似一个很简单的问题,却很容易出bug。不妨把这个问题当做一道面试题目,我想一定能难道不少的人。今天就给大家说一下在ArrayList循环遍历并删除元素的问题。首先请看下面的例子: 1234567891011121314151617181920212223import java.util.ArrayList;public class ArrayListRemove{  public static void main(String[]args)  {    ArrayList<String>list=newArrayList<String>();    list.add("a");    list.add("b");    list.add("b");    list.add("c");    list.add("c");    list.add("c");    remove(list);    for(Strings:list)    ...
阅读全文 »

一直想搞懂的字符编码问题

发表于 2020-02-13 | 更新于: 2020-08-02 | 分类于 编码
背景​ 从你刚刚毕业开始最怕的问题就是乱码问题对不对?起码我是。后面渐渐的知道是编码问题,而后面为了出现这种问题就都选择UTF-8,然后后面渐渐的就开始淡忘了这个问题。然后当小弟弟小妹妹问我们这相关的问题的时候,也都是跟他们说,全部改成UTF-8就好了。 ​ 但这是一种逃避,其实编码问题困扰我好多年,其实说句实话,真的没有搞懂。之前还有同事在一起相互考问 一个中文到底占用几个字节? 对不对,你遇到过吗?你回答的上来吗?哈哈 推荐几个常用的地址: ASCII:http://tool.oschina.net/commons?type=4 GB2312简体中文编码表:http://tools.jb51.net/table/gb2312 Unicode编码:http://tool.chinaz.com/Tools/Unicode.aspx 常见的编码ASCII​ 它是现今最早最通用的单字节编码系统,并等同于国际标准ISO/IEC 646,其中一个英文字母(不分大小写)占一个字节的空间。 引申:字节是指一小组相邻的二进制数码。通常是8位作为一个 ...
阅读全文 »

一文带你快速掌握AQS

发表于 2020-02-12 | 更新于: 2020-08-02 | 分类于 Java
作者:薛8 来源:https://juejin.im/post/5c890b4a51882501351d5929 AQS简介AbstractQueuedSynchronizer抽象队列同步器,简称为AQS,可用于构建阻塞锁或者其他相关同步器的基础框,是Java并发包的基础工具类。通过AQS这个框架可以对同步状态原子性管理、线程的阻塞和解除阻塞、队列的管理进行统一管理。 AQS是抽象类,并不能直接实例化,当需要使用AQS的时候需要继承AQS抽象类并且重写指定的方法,这些重写方法包括线程获取资源和释放资源的方式(如ReentractLock通过分别重写线程获取和释放资源的方式实现了公平锁和非公平锁),同时子类还需要负责共享变量state的维护,如当state为0时表示该锁没有被占,大于0时候代表该锁被一个或多个线程占领(重入锁),而队列的维护(获取资源失败入队、线程唤醒、线程的状态等)不需要我们考虑,AQS已经帮我们实现好了。AQS的这种设计模式采用的正是模板方法模式。 总结起来子类的任务有: 通过CAS操作维护共享变量state。 重写资源的获取方式。 重写资源释放的方式。 如果对 ...
阅读全文 »

序列化和反序列化的底层实现原理是什么?

发表于 2020-02-11 | 更新于: 2020-08-02 | 分类于 Java
基本概念1、什么是序列化和反序列化(1)Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程; (2)序列化:对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性。序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。序列化后的字节流保存了Java对象的状态以及相关的描述信息。序列化机制的核心作用就是对象状态的保存与重建。 (3)反序列化:客户端从文件中或网络上获得序列化后的对象字节流后,根据字节流中所保存的对象状态及描述信息,通过反序列化重建对象。 (4)本质上讲,序列化就是把实体对象状态按照一定的格式写入到有序字节流,反序列化就是从有序字节流重建对象,恢复对象状态。 2、为什么需要序列化与反序列化我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等, 而这些数据都会以二进制序列的形式在网络上传送。 那么当两个Java进程进行通信时,能否实现进程间的对象传送呢?答案是可以的!如何做到呢?这就需要Java序列化与反序列化了! 换句话说,一方面,发送 ...
阅读全文 »

使用SimpleDateFormat的时候小心点

发表于 2020-02-10 | 更新于: 2020-08-02 | 分类于 Java
SimpleDateFormat是Java提供的一个格式化和解析日期的工具类,日常开发中应该经常会用到,但是由于它是线程不安全的,多线程公用一个SimpleDateFormat实例对日期进行解析或者格式化会导致程序出错。 代码示例演示写一段小Demo来模拟多线程下SimpleDateFormat做时间格式化的时候报错,代码如下: 123456789101112131415161718192021222324252627282930package com.vernon.test.demo.jdk.text;import java.text.ParseException;import java.text.SimpleDateFormat;/** * Created with vernon-test * Description: * User:chenyuan * Date:2019/3/20 Time:2:03 PM */public class SimpleDateFormatCase { //1、创建单例实例 static SimpleDateFormat sdf ...
阅读全文 »

使用HashMap的时候小心点

发表于 2020-02-09 | 更新于: 2020-08-02 | 分类于 HashMap , Java
Map家族介绍我们都知道HashMap是线程不安全的,但是HashMap的使用频率在所有Map中确实属于比较高的。因为它可以满足我们大多数的场景了。 看一眼Map家族的关系图: Map是一个接口,我们常用的实现类有HashMap、LinkedHashMap、TreeMap,HashTable。 HashMapHashMap根据key的·值来保存value,需要注意的是,HashMap不保证遍历的顺序和插入的顺序是一致的。HashMap允许有一条记录的key为null,但是对值是否为null不做要求。 HashTableHashTable类是线程安全的,它使用synchronize来做线程安全,全局只有一把锁,在线程竞争比较激烈的情况下hashtable的效率是比较低下的。因为当一个线程访问hashtable的同步方法时,其他线程再次尝试访问的时候,会进入阻塞或者轮询状态,比如当线程1使用put进行元素添加的时候,线程2不但不能使用put来添加元素,而且不能使用get获取元素。所以,竞争会越来越激烈。相比之下,ConcurrentHashMap使用了分段锁技术来提高了并发度,不在同一段 ...
阅读全文 »

什么是Java内存模型?

发表于 2020-02-08 | 更新于: 2020-08-02 | 分类于 Java
前言要想深入了解Java并发编程,就要先理解好Java内存模型,而要理解Java内存模型又不得不从硬件、计算机内存模型说起,本文从计算机内存模型产生的原因、解决的问题谈起,然后再对Java模型进行介绍,最后对计算机内存模型和Java内存模型进行总结,希望大家看完本文之后有所收获! CPU工作过程及出现的问题CPU执行过程大家都知道,计算机在执行程序时,每条指令都是在CPU中执行的,而执行的时候,又免不了要和数据打交道,而计算机上面的临时数据,是储存在主存中的。 计算机内存包括高速缓存和主存。 我们知道CPU执行指令的速度比从主存读取数据和向主存写入数据快很多,所以为了高效利用CPU,CPU增加了高速缓存(cache)来匹配CPU的执行速度,最终程序的执行过程如下 首先会将数据从主存中复制一份到CPU的高速缓存中 当CPU执行计算的时候就可以直接从高速缓存中读取数据和写入数据 当运算结束后,再将高速缓存的数据更新到主存中 缓存一致性问题上面的执行过程在单线程情况下并没有问题,但是在多线程情况下就会出现问题,因为CPU如果含有多个核心,则每个核心都有自己独占高速缓存,如果出现多个线 ...
阅读全文 »

深入理解Linux的CPU上下文切换

发表于 2020-02-07 | 更新于: 2020-08-02 | 分类于 Linux
如何理解Linux的上下文切换 Linux 是一个多任务操作系统,它支持同时运行的任务数量远大于 CPU 个数。其实这些任务没有真正的同时运行,是因为系统在很短的时间内,将 CPU 轮流分配给它们,造成多任务同时运行的错觉。 而在每个任务运行前,CPU 都需要知道任务从哪里加载、从哪里开始运行,需要系统事先设置好 CPU 寄存器和程序计数器。CPU 寄存器是 CPU 内置的容量小、速度极快的内存。而程序计数器则是用来存储 CPU 正在执行的指令位置、或即将执行的下一条指令位置。它们都是 CPU 在运行任务前必须依赖的环境,也被叫做 CPU 上下文。 上下文切换,就是先把前一个任务的 CPU 上下文保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳到程序计数器所指的新位置,运行新任务。而这些保存下来的上下文,会存储在系统内核中,并在任务重新调度执行时再次加载进来。这样就能保证任务原来的状态不受影响,让任务看起来还是连续运行。 根据任务的不同,CPU 的上下文切换可以分为几个不同的场景,也就是:进程上下文切换、线程上下文切换、中断上下文切换。 进程上下文切换1、用户空间与 ...
阅读全文 »

深入分析synchronized原理和锁膨胀过程

发表于 2020-02-06 | 更新于: 2020-08-02 | 分类于 Java
前言上一篇文章介绍了多线程的概念及synchronized的使用方法《synchronized的使用(一)》,但是仅仅会用还是不够的,只有了解其底层实现才能在开发过程中运筹帷幄,所以本篇探讨synchronized的实现原理及锁升级(膨胀)的过程。 synchronized实现原理synchronized是依赖于JVM来实现同步的,在同步方法和代码块的原理有点区别。 同步代码块我们在代码块加上synchronized关键字 12345public void synSay() { synchronized (object) { System.out.println("synSay----" + Thread.currentThread().getName()); }} 编译之后,我们利用反编译命令javap -v xxx.class查看对应的字节码,这里为了减少篇幅,我就只粘贴对应的方法的字节码。 12345678910111213141516171819202122232425262728293031323334353 ...
阅读全文 »
上一页1…101112…15下一页
Vernon

Vernon

149 日志
66 分类
87 标签
RSS
GitHub E-Mail
© 2021 Vernon
由 Hexo 强力驱动
|
主题 — NexT.Gemini v6.0.4