notifyAll(): 在上两次中对于Object的wait()和notify()方法的官方doc进行了通读,上一次https://www.cnblogs.com/webor2006/p/11407966.html读了notify()的说明,接下来再来读一下notifyAll()方法的说明,先看下它的声明,也是native的: 开始逐字解读: 从上面描述可以看到,其实它跟notify()方法的作用是差不多的,只是该方法是唤醒所有的线程,但是注意:唤醒的线程是不会立马执行的,需要跟普通的其它线程…
在上一节中对Object的wait.notify.notifyAll方法进行了总结,这次举一个具体案例来进行巩固,题目如下: 编写一个多线程程序,实现这样的一个目标: 1.存在一个对象,该对象有一个int类型的成员变量counter,该成员变量的初始值为0. 2.创建两个线程,其中一个线程对该对象的成员变量counter增1,另一个线程对该对象的成员变量减1. 3.输出该对象成员变量counter每次变化后的值. 4.最终输出的结果应为:101010101010.... 分析: 1.会创建两个线…
新建线程 新建线程很简单.只需要使用new关键字创建一个线程对象,然后调用它的start()启动线程即可. Thread thread1 = new Thread1(); t1.start(); 那么线程start()之后,会干什么呢?线程有个run()方法,start()会创建一个新的线程并让这个线程执行run()方法. 这里需要注意,下面代码也能通过编译,也能正常执行.但是,却不能新建一个线程,而是在当前线程中调用run()方法,将run方法只是作为一个普通的方法调用. Thread thr…
高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求,而且也能怎么你在整个项目中的一个处理逻辑的能力体现.那么,你真的知道什么是高并发吗?这不是一个很简单的话题.高并发,往往会牵扯到很多的问题,如何才能快速响应,如何处理各个线程之间的交互,如何完成逻辑之间的高负载运转,甚至,一个系统,如果没有做好前期高并发的合理配置,整个产品会遇到瓶颈,以及不可预期的…
java高并发系列第11篇文章. 本文主要探讨一下中断线程的几种方式. 通过一个变量控制线程中断 代码: package com.itsoku.chat05; import java.util.concurrent.TimeUnit; /** * 微信公众号:路人甲Java,专注于java技术分享(带你玩转 爬虫.分布式事务.异步消息服务.任务调度.分库分表.大数据等),喜欢请关注! */ public class Demo1 { public volatile static boolean e…
这是并发系列第10篇文章. 什么是线程安全? 当多个线程去访问同一个类(对象或方法)的时候,该类都能表现出正常的行为(与自己预想的结果一致),那我们就可以所这个类是线程安全的. 看一段代码: package com.itsoku.chat04; /** * 微信公众号:路人甲Java,专注于java技术分享(带你玩转 爬虫.分布式事务.异步消息服务.任务调度.分库分表.大数据等),喜欢请关注! */ public class Demo1 { static int num = 0; public…
线程组 我们可以把线程归属到某个线程组中,线程组可以包含多个线程以及线程组,线程和线程组组成了父子关系,是个树形结构,如下图: 使用线程组可以方便管理线程,线程组提供了一些方法方便方便我们管理线程. 创建线程关联线程组 创建线程的时候,可以给线程指定一个线程组,代码如下: package com.itsoku.chat02; import java.util.concurrent.TimeUnit; /** * <b>description</b>: <br> * &l…
Java是最早开始有并发的语言之一,再过去传统多任务的模式下,人们发现很难解决一些更为复杂的问题,这个时候我们就有了并发. 引用 多线程比多任务更加有挑战.多线程是在同一个程序内部并行执行,因此会对相同的内存空间进行并发读写操作.这可能是在单线程程序中从来不会遇到的问题.其中的一些错误也未必会在单CPU机器上出现,因为两个线程从来不会得到真正的并行执行.然而,更现代的计算机伴随着多核CPU的出现,也就意味着不同的线程能被不同的CPU核得到真正意义的并行执行. 那么,要开始Java并发之路,就要开…
[实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象引用:AtomicStampedReference [实战Java高并发程序设计 4]数组也能无锁:AtomicIntegerArray [实战Java高并发程序设计 5]让普通变量也享受原子操作 [实战Java高并发程序设计6]挑战无锁算法:无锁的Vector实现 在对线程池的介绍中,提到了一个非…
wait(): 在上一次https://www.cnblogs.com/webor2006/p/11404521.html中对于无参数的wait()方法的javadoc进行了解读,而它是调用了一个参数的重载方法,回忆下: 其中如果传0代表无限等待,否则是等待指定的时间就会停止等待,如参数所示: 这个版本的注释比无参的要详细很多,所以..继续来解读它,不过它里面有一些上次看到无参wait()的说明,就简单略过了,不重复进行说明,好,下面文档阅读走起: 以上就是为啥我们在学习wait()时在实际代码…
在上一次https://www.cnblogs.com/webor2006/p/11792954.html对于Lock的具体实现类ReentrantLock用了一个示例对它进行了一个简单的了解,而它其实里面有很多东东,不过得循序渐进一步步来,目前还不适合来从底层分析它,另外在上次对于Lock和syncronized对于同步的区别做了一个文字的总结,这里回顾一下,相当之重要: 而对于Lock这个接口其实提供的方法是比较少的,纵览一下: 其中大部分都是跟锁相关的方法,除了标红的这个是跟一个新的Con…
上一次https://www.cnblogs.com/webor2006/p/11442551.html中通过openjdk从c++的底层来审视了ObjectMonitor的底层实现,这次继续来探究底层,对于wait()和notify()的底层细节到底是啥样的呢?下面还是先来到openjdk中来打开ObjectMonitor.hpp,其中它里面有一个很重要的类: 然后我们要分析的wait()和notify()是在它的cpp实现文件中,所以打开ObjectMonitor.cpp来直奔主题: 其中我…
关于死锁其实在之前https://www.cnblogs.com/webor2006/p/10659938.html的jvm学习中已经详细举过例子了,不过这里再来复习一下,另外是从并发这个专题领域的角度再来看下它,这里先来阐述一下相关的概念: 死锁:线程1等待线程2互斥持有的资源,而线程2也在等待线程1互斥持有的资源,两个线程都无法继续执行. 活锁:线程持续重试一个总是失败的操作,导致无法继续执行. 饿死:线程一直被调度器延迟访问其赖以执行的资源,也许是调度器先于低优先级的线程而执行高优先级的线…
java并发的学习从去年就已经中断了,之前只对于java并发的一些基础进行了一些巩固,对于这个硬技能不管是对于面试还是对于日常的实际开发来说都非常之重要,所以接下来给自己重新定一个新目标,准备重拾它一步一个脚印从易到难彻底的将Java并发所涉及的方方面面进行一个深入的学习,向着“精通”的程度来努力,当然要想达到此目标肯定得把自己扒一层皮,不可能这么轻松的,所以贵在坚持! Thread: "万丈高楼平地起",为了达到“精通”的目标,肯定还得从基础一点点开始,虽说是比较枯燥,但是这是让自己…
1. 什么是线程? 线程和进程的区别 在了解线程的概念前,我们应该先知道什么是进程? 进程是操作系统的基本概念之一, 它是正在执行的程序实例. * 下面的一些进程的基本概念你可以了解下 -------------------------------------------------------------------- 操作系统逻辑上将一个进程分为以下几部分(段): # 文本 程序的指令 # 数据 程序使用的静态变量 # 堆 程序可从该区域动态分配额外内存 # 栈 随函数调用和返回而增减的一片…
摘自马士兵java并发编程 一.认识Executor.ExecutorService.Callable.Executors /** * 认识Executor */ package yxxy.c_026; import java.util.concurrent.Executor; public class T01_MyExecutor implements Executor { public static void main(String[] args) { new T01_MyExecutor(…
对于synchronized关键字,我们在实际使用时可能经常听说用它是一个非常重的操作,其实这个“重”是要针对JDK的版本来说的,如今JDK已经到了12版本了,其实对这个关键字一直是存在偏见的,它底层也发生了很多的变化,所以我们也得随着JDK的版本将知识进行更新才行,所以这节继续针对锁进行深入的探讨. 在JDK 1.5之前,我们若想实现线程同步,只能通过synchronized关键字这一种方式来达成:底层,Java也是通过synchronized关键字来做到数据的原子性维护的:synchroni…
自旋对于synchronized关键字的底层意义与价值分析: 对于synchronized关键字的底层意义和价值分析,下面用纯理论的方式来对它进行阐述,自旋这个概念就会应运而生,还是很重要的,下面阐述下: JVM中的同步是基于进入与退出监视器对象(Monitor,也叫管程对象)来实现的,每个对象实例都会有一个Monitor对象,Monitor对象会和Java对象一同创建并销毁.Monitor对象是由C++来实现的[未来会通过openjdk来分析C++的底层实现的]. 当多个线程同时访问一段同步代…
在上一次https://www.cnblogs.com/webor2006/p/11372521.html中对于Thread类和Runnable接口有了一个基本的认识,这次咱们继续巩固基础,首先先新建一个全新的工程,专门用来学习Java并发相关的: 好,下面先来对Object中的wait()和Thread.sleep()方法进行官方说明解读: wait(): 打开Object类可以发现wait()方法有几个重载形式的: 其中我们平常常用的一般都是无参的,如: 其中又调用了一个带参数的,发现也是n…
继续上一次https://www.cnblogs.com/webor2006/p/11890688.html的Condition接口说明进行阅读: 上面这个程序会在之后手动来实现一下,说实话这种写法在实际工作中用得不多,自己也完全写不出来,感受一下Lock.Condition的写法,其中Condition的调用一定是要在获取Lock()之后才能使用,看一下范例的写法: 而对比一下咱们之前传统的代码: 继续往下阅读: 这里再来提一个这个“spurious wakeup”,假幻醒,也就是除了调用了n…
在上两次中已经将Lock这个接口的整个官方说明进行了阅读,这次来了解一下它的一个非常重要的实现类: 啥叫“可重入”呢?其实是指一个线程已经拿到了锁,然后该线程还能再次获取这把锁,接下来在了解它之前先用一下该锁,如下: 然后接一来线程分别来调用定义的两个方法,如下: 下面来执行一下: 也就是线程交替地在执行,很容易理解,那如果下面修改一下代码: 那结果又是咋样呢?肯定会发生阻塞的情况,因为用了锁木有解锁嘛,运行一下: 也很好理解嘛,由于两个方法都要用同一个锁: 那当线程执行了myMethod1之后…
在上一次https://www.cnblogs.com/webor2006/p/11446473.html中对锁的升级进行了一个比较详细的理论化的学习,先回忆一下: 编译器对于锁的优化措施: 锁消除技术: 接下来则会通过实例来分析一下JIT编译器优化的一些方式,先来看第一个例子: 很简单的程序,然后反编译看一下它在字节码的表现: 接下来则来修改一下程序: 其实反编译的字节码的锁还是会有的: 但是很明显这段同步的意义就不大了,因为每个线程在访问这个方法时的局部变量肯定都是不一样的,不同的对象锁也不…
在上一次https://www.cnblogs.com/webor2006/p/11428408.html中对于synchronized关键字的作用做了一个实例详解,下面再来看一下这个程序: 请问下,如果一个线程访问了同一个对象的method1()方法之后,另外一个线程能否访问同一个对角的method4的静态方法呢?答案是肯定的,因为method1的锁是锁的对象,而method4锁的是MyClass的类对象,锁是不一样的,当然就可以并行的进行访问啦, 关于synchronized其实从使用角度来…
关于synchronized关键字原理其实在当时JVM的学习[https://www.cnblogs.com/webor2006/p/9595300.html]中已经剖析过了,这里从研究并发专题的角度再来审视一下它,毕境对于并发它是非常之重要的,下面先来看一下程序: 然后运行,其结果会不定的,有正常依次按顺序执行直到程序退出的,如下: 也有不如预期的,如: 写这个程序的目的其实并不是说同步的问题,而是关于多线程如果对象中存在一个可修改的变量,对于多线程是可以被共享的,所以上面结果的不稳定心就是由…
从这次开始接触Java1.5推出的并发包中的东东,先看一下jdk中的并发包: 接下来咱们则会集中对这些并发包中的核心进行深入了解,不光要学会怎么用这些并发包中的类,而且还得知道这些功能背后运行的原理, 所以手踏实地的一步步从基础开始展开对它的剖析,在JDK1.5之前要想对代码进行同步只有一个选择,利用syncronized关键字,但是在之后推出了一个全新的同步方式,那就是Lock锁,这个我们在实际工作中也会经常看到它的使用,下面瞅下它: 而在并发包中很多的组件都是直接或者间接的来源于它,瞅一眼:…
在上一次https://www.cnblogs.com/webor2006/p/11446129.html的理论的最后谈到了锁的演化,如下: 下面具体来阐述一下: 偏向锁:它是针对一个线程来说, 它的主要作用就是优化同一个线程多次获取一个锁的情况:如果一个synchronized方法被一个线程访问,那么这个方法所在的对象就会在其Mark Word中将偏向锁进行标记,同时还会有一个字段来存储该线程的ID;当这个线程再次访问一个synchronized方法时,它会检查这个对象的Mark Word的偏…
继续基于上一次https://www.cnblogs.com/webor2006/p/11428811.html来研究synchronized关键字在字节码中的表现,在上一次文末提出了一个这样的问题: 其对应的源代码如下: 这是因为上面这个同步块中的代码会有抛异常的情况发生,虽说我们肉眼看着好像只有一条打印语句,但是JVM需要考虑同步块抛异常的情况其锁也要正常被释放,所以我们可以看到有异常抛出相关的助记符: 所以可以总结一下:“当我们使用synchronized关键字来修饰代码块时,字节码层面上…
在上一次https://www.cnblogs.com/webor2006/p/11422587.html中通过实践来解了一个案例,先来回顾一下习题: 编写一个多线程程序,实现这样的一个目标: 1.存在一个对象,该对象有一个int类型的成员变量counter,该成员变量的初始值为0. 2.创建两个线程,其中一个线程对该对象的成员变量counter增1,另一个线程对该对象的成员变量减1. 3.输出该对象成员变量counter每次变化后的值. 4.最终输出的结果应为:101010101010....…
转自:https://blog.csdn.net/gududedabai/article/details/80815666…
在上两次已经对Condition这个类的javadoc进行了完整的解读,接下来则对它里面的方法进行一下纵览,并进行官方的解读,如下: 下面一一来读一下各个方法的说明: await(): 上面这段说明已经道出了这个方法的核心作用,非常重要,继续来看一下这四种情况是哪四种? 接下来是实现上的考量,简单看一下既可: awaitUninterruptibly(): 在了解了第一个await()方法之后,这个就比较好理解了,就是它的一个特例,也就是不响应中断而已,可以稍看一下它的说明: awaitNano…