
Java并发编程
老周聊架构
微信公众号:老周聊架构
展开
-
Synchronized关键字的原理以及用法
一、Sychronized的简介Sychronized的作用官方解释:同步方法支持一种简单的策略来防止线程干扰和内存一致性错误;如果一个对象对多个线程可见,则对该对象变量的所有读取或写入都是通过同步方法完成的。 我的理解:能够保证在同一时刻最多只有一个线程执行该段代码,以达到保证并发安全的效果。Sychronized的地位Sychronized是java的关键字,被java语...原创 2019-01-19 16:16:16 · 513 阅读 · 0 评论 -
spring的controller是单例还是多例,怎么保证并发的安全。
答案:controller默认是单例的,不要使用非静态的成员变量,否则会发生数据逻辑混乱。正因为单例所以不是线程安全的。我们下面来简单的验证下:package com.riemann.springbootdemo.controller;import org.springframework.context.annotation.Scope;import org.springframew...原创 2019-07-29 23:48:06 · 28024 阅读 · 27 评论 -
讲讲java同步机制的wait和notify
1、wait和notify的使用与区别对于wait()和notify()的理解,还是要从jdk官方文档中开始,在Object类方法中有:void notify() Wakes up a single thread that is waiting on this object’s monitor.译:唤醒在此对象监视器上等待的单个线程void notifyAll() Wakes up...原创 2019-08-03 16:09:49 · 1396 阅读 · 0 评论 -
CAS机制是什么,如何解决ABA问题
将之前我们先来了解独占锁和乐观锁。独占锁:是一种悲观锁,synchronized就是一种独占锁,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁。乐观锁:每次不加锁,假设没有冲突去完成某项操作,如果因为冲突失败就重试,直到成功为止。一、CAS 操作乐观锁用到的机制就是CAS,Compare and Swap。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值...原创 2019-08-03 18:06:37 · 5005 阅读 · 0 评论 -
可重入锁/不可重入锁,公平锁/非公平锁,乐观锁/悲观锁,独享锁/共享锁,偏向锁/轻量级锁/重量级锁,分段锁,自旋锁
在并发编程中,会涉及到各种各样的锁,这篇文章主要介绍各种锁的分类以及作用。介绍的内容如下:可重入锁/不可重入锁公平锁/非公平锁乐观锁/悲观锁独享锁/共享锁偏向锁/轻量级锁/重量级锁分段锁自旋锁上面是很多锁的名词,这些分类并不是全是指锁的状态,有的指锁的特性,有的指锁的设计,下面总结的内容是对每个锁的名词进行一定的解释。1、可重入锁/不可重入锁可重入锁广义上的可重入锁指的...原创 2019-07-22 23:55:22 · 1161 阅读 · 0 评论 -
Java并发编程中的原子类总结
一、原子类介绍在并发编程中很容易出现并发安全的问题,有一个很简单的例子就是多线程更新变量i=1,比如多个线程执行i++操作,就有可能获取不到正确的值,而这个问题,最常用的方法是通过Synchronized进行控制来达到线程安全的目的(关于synchronized可以看这篇文章)。但是由于synchronized是采用的是悲观锁策略,并不是特别高效的一种解决方案。实际上,在J.U.C下的atomi...原创 2019-07-27 21:05:17 · 568 阅读 · 0 评论 -
源码解读之(四)AbstractQueuedSynchronizer
一、简介AbstractQueuedSynchronizer 队列同步器(AQS)是一个抽象类,,它是为实现依赖于先进先出(FIFO)等待队列的阻塞锁和相关同步器(信号量,事件等)提供的一个基础框架。AQS继承了AbstractOwnableSynchronizer类,这个类为创建锁和相关同步器提供了基础。AQS是Concurrent包的核心,lock就是在AQS的基础上实现的,阻塞队列,线程池...原创 2019-08-08 00:34:24 · 532 阅读 · 0 评论 -
Java并发编程中常见的并发工具类
今天有时间看了下《Java并发编程的艺术》这本书,看到并发用到的工具类,故记录之。如果有朋友需要电子版的可以在下面百度网盘进行下载:《Java并发编程的艺术》接下来我们进入正题,JDK中的并发包里,提供了几个非常有用的并发工具类。CountDownLatch、CyclicBarrier 和 Semaphore工具类提供了一种并发流程控制的手段。Exchanger工具类则提供了在线程间交换...原创 2019-07-28 00:08:00 · 595 阅读 · 0 评论 -
Java并发编程中四种线程池
我们先来看一下下面这个问题!!!Question:用过线程池吗,如果用过,请说明原理,并说说newCache和newFixed有什么区别,构造函数的各个参数的含义是什么,比如coreSize,maxsize等。Answer:newSingleThreadExecutor返回一个包含单线程的Executor,将多个任务交给此Executor时,这个线程处理完一个任务后接着处理下一个任务,若...原创 2019-07-28 18:52:01 · 4371 阅读 · 0 评论 -
用三个线程按顺序循环打印abc三个字母,比如abcabcabc(四种方式实现)
这道题看似简单,实则考察了你对多线程的重要知识的掌握情况。总体思路就是我们三个线程用同一把锁,刚开始,a线程获取锁,打印a,设置下一个打印b,并同时唤醒bc,这时候,bc线程都阻塞等待,如果c抢到了锁,进入代码执行,由于不符合条件,会wait(同时释放锁),直到b抢到锁,符合条件打印,如此,顺序执行下去。这里提供以下几种方法:一、Synchronized同步法使用同步块和wait、notif...原创 2019-08-02 00:29:05 · 6623 阅读 · 2 评论 -
源码解读之(五)ReentrantReadWriteLock(中)
上篇主要讲的ReentrantReadWriteLock的几个核心变量:源码解读之(五)ReentrantReadWriteLock(上)这篇中篇主要来讲解讲解ReentrantReadWriteLock的ReadLock的加锁和减锁过程。三、ReadLockReentrantReadWriteLock的ReadLock加锁解锁过程依赖于AQS类,所以有些相同的逻辑可以看看Reentra...原创 2019-08-18 18:05:35 · 308 阅读 · 0 评论 -
源码解读之(五)ReentrantReadWriteLock(下)
上篇的中篇主要讲的ReentrantReadWriteLock的ReadLock的加锁和减锁过程:源码解读之(五)ReentrantReadWriteLock(中)这篇下篇主要来讲解讲解ReentrantReadWriteLock的WriteLock的加锁和减锁过程。四、WriteLockReentrantReadWriteLock的WriteLock加锁解锁过程依赖于AbstractQ...原创 2019-08-18 18:42:00 · 301 阅读 · 0 评论 -
导致线程死锁的原因?怎么解除线程死锁
一、导致线程死锁的原因多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放,而该资源又被其他线程锁定,从而导致每一个线程都得等其它线程释放其锁定的资源,造成了所有线程都无法正常结束。这是从网上其他文档看到的死锁产生的四个必要条件:1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用。2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。...原创 2019-08-14 23:35:46 · 4544 阅读 · 0 评论 -
countdowlatch 和 cyclicbarrier的用法以及区别
1、CountDownLatch一个非常典型的应用场景是:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行。假如我们这个想要继续往下执行的任务调用一个CountDownLatch对象的await()方法,其他的任务执行完自己的任务后调用同一个CountDownLatch对象上的countDown()方法,这个调用await()方法的任务将一直阻塞等待,直到这个Count...原创 2019-08-12 23:06:09 · 602 阅读 · 0 评论 -
源码解读之(五)ReentrantReadWriteLock(上)
一、前言在Java并发包中常用的锁(如:ReentrantLock),基本上都是排他锁,这些锁在同一时刻只允许一个线程进行访问,而读写锁在同一时刻可以允许多个读线程访问,但是在写线程访问时,所有的读线程和其他写线程均被阻塞。读写锁维护了一对锁,一个读锁和一个写锁,通过分离读锁和写锁,使得并发性相比一般的排他锁有了很大提升。相对于排他锁,提高了并发性。在实际应用中,大部分情况下对共享数据(如缓存...原创 2019-08-18 02:49:19 · 328 阅读 · 0 评论 -
并发编程实现生产者和消费者模式
一、简介生产者和消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此并不直接通信,而是通过阻塞队列进行通信,所以生产者生产完数据后不用等待消费者进行处理,而是直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列中获取数据,阻塞队列就相当于一个缓冲区,平衡生产者和消费者的处理能力。二、实现方式1、synchronized、wait和notify生产者和消费者线...原创 2019-07-20 02:09:50 · 911 阅读 · 0 评论 -
线程池的关闭方式有几种,各自的区别是什么。
一、概述Java提供的接口 java.util.concurrent.ExecutorService是一种异步执行的机制,可以让任务在后台执行。其实例就像一个线程池,可以对任务进行统一的管理。二、研究Java提供的对ExecutorService的关闭方式有两种,一种是调用其shutdown()方法,另一种是调用shutdownNow()方法。这两者是有区别的。以下内容摘自源代码内的注释...原创 2019-07-29 00:28:55 · 5179 阅读 · 0 评论 -
Lock与Synchronized的区别
两者区别1、首先synchronized是java内置关键字,在jvm层面,Lock是个java类;2、synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;3、synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;4...原创 2019-07-18 23:18:30 · 1228 阅读 · 2 评论 -
使用HashMap在什么情况会出现内存泄漏?
Q:在Java中怎么可以产生内存泄露?A:Java中,造成内存泄露的原因有很多种。典型的例子是一个没有实现hasCode和equals方法的Key类在HashMap中保存的情况。最后会生成很多重复的对象。所有的内存泄露最后都会抛出OutOfMemoryError异常,下面通过一段简短的通过无限循环模拟内存泄露的例子说明一下。package com.test;import java.util...原创 2019-04-21 01:25:23 · 11131 阅读 · 2 评论 -
Java多线程的五种实现方式
Java多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。一、第一种方式:继承Thread类万物皆对象,那么线程也是对象,对象就应该能够抽取其公共特性封装成为类,使用类可以实例化多个对象,那么实现线程的第一种方式就是继...原创 2019-07-13 17:14:27 · 1193 阅读 · 0 评论 -
volatile的原理与作用
一、概念volatile关键字表示被修饰的变量的值容易变化( 即被其他线程更改 )。因而不稳定。volatile变量的不稳定性意味着对这种变量的读和写操作都必须从高速缓存或者主内存。(也是通过高速缓存读取)中读取,以读取变量的相对新值。因此,volatile变量不会被编译器分配到寄存器进行存储,对 volatile 变量的读写操作都是内存访问( 访问高速缓存相当于主内存 )操作。volati...原创 2019-07-13 19:13:47 · 1679 阅读 · 2 评论 -
Java实现一个线程安全的循环单链表
有时候会有需要这样的场景,需要一个循环的链表做一些重复性的工作,比方说我们设计定时任务的时候,按照每一秒前进一个进行定时任务的读取,那么就需要有一个循环链表来做这样的数据结构,而java没有提供这样的一个数据结构,我在项目开发的时候也遇到了这样的问题,我们需要有管理定时任务,使用一个触发器来触发这些任务。定义接口:package com.algorithm.list;/** * 循环链表...原创 2019-07-14 02:50:26 · 1238 阅读 · 2 评论 -
sleep和sleep(0)的区别
Sleep 接口均带有表示睡眠时间长度的参数 timeout。调用以上提到的 Sleep 接口,会有条件地将调用线程从当前处理器上移除,并且有可能将它从线程调度器的可运行队列中移除。这个条件取决于调用 Sleep 时timeout 参数。当 timeout = 0, 即 Sleep(0),如果线程调度器的可运行队列中有大于或等于当前线程优先级的就绪线程存在,操作系统会将当前线程从处理器上移除,调...原创 2019-07-16 00:06:31 · 2282 阅读 · 0 评论 -
画一个线程的生命周期状态图
一、线程的生命周期线程状态转换图:1、新建状态(New)用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态。处于新生状态的线程有自己的内存空间,通过调用start方法进入就绪状态(runnable)。注意:不能对已经启动的线程再次调用start()方法,否则会出现java.lang.IllegalThreadStateException异常。2、就绪状态...原创 2019-07-16 00:43:46 · 8069 阅读 · 2 评论 -
调用A接口返回a耗时1分钟,调用B接口返回b耗时1分钟,怎么使得a+b在1分钟左右
不知道大家面试的时候有遇到这种类似的问题,面试官其实考察的知识点还是有那么多的。我觉得考察的知识点有:1、同步以及异步的选择2、并发编程带参数的异步调用一看这个问题,显然是选择异步,因为同步的话你得等调用A接口完成后,再调用B接口,这个耗时就2分钟了,显然不行。选择异步的话,A接口调用完和B接口调用完互不影响。AsyncController.javapackage com.riemann...原创 2019-09-13 18:50:07 · 1040 阅读 · 0 评论