JAVA多线程
文章平均质量分 83
文章以书籍JAVA并发编程之美为参考依据
Small mushroom cool
这个作者很懒,什么都没留下…
展开
-
JAVA并发编程高级——原子变量操作类(AtomicLong)
JUC 并发包中包含有 AtomicInteger、AtomicLong 和 AtomicBoolean 等原子性操作类,它们的原理类似,本文讲解 AtomicLong类。Atomicong 是原子性递增或者递减类,其内部使用 Unsafe 来实现,我们看下面的代码。以上是AtomicLong的源码代码(1)通过 Unsafe.getUnsafe()方法获取到 Unsafe 类的实例,这里你可能会有疑问,为何能通过 Unsafe.getUnsafe()方法获取到 Unsafe 类的实例?原创 2024-09-29 11:18:32 · 489 阅读 · 0 评论 -
JAVA线程基础——线程的创建和常用方法
如上代码中的 MyThread 类继承了 Thread 类,并重写了run()方法。在 main 函数里面创建了一个 MyThread 的实例,然后调用该实例的start 方法启动了线程。需要注意的是,当创建完 thread 对象后该线程并没有被启动执行,直到调用了start方法后才真正启动了线程。其实调用 start 方法后线程并没有马上执行而是处于就绪状态,这个就绪状态是指该线程已经获取了除 CPU 资源外的其他资源,等待获取 CPU 资源后才会真正处于运行状态。原创 2024-09-09 17:37:44 · 664 阅读 · 0 评论 -
JAVA线程基础——ThreadLocal的使用和原理
如图1-6所示,在每个线程内部都有一个名为threadLocals的成员变量,该变量的类型为 HashMap,其中 key 为我们定义的 ThreadLocal 变量的 this引用,value 则为我们使用set方法设置的值。每个线程的本地变量存放在线程自己的内存变量threadLocals中,如果当前线程一直不消亡,那么这些本地变量会一直存在,所以可能会造成内存溢出,因此使用完毕后要记得调用 ThreadLocal的remove 方法删除对应线程的threadLocals中的本地变量。原创 2024-09-12 11:32:48 · 2027 阅读 · 0 评论 -
JAVA线程基础——InheritableThreadLocal的使用和原理
InheritableThreadLocal类通过重写代码(2)和(3)让本地变量保存到了具体线程的 inheritableThreadLocals变量里面,那么线程在通过InheritableThreadLocal 类实例的 set 或者 get 方法设置变量时,就会创建当前线程的inheritableThreadLocals 变量。原创 2024-09-12 12:23:39 · 653 阅读 · 0 评论 -
JAVA线程基础二——并发编程基础知识
首先要澄清并发和并行的概念,并发是指同一个时间段内多个任务同时都在执行,并且都没有执行结束,而并行是说在单位时间内多个任务同时在执行。并发任务强调在一个时间段内同时执行,而一个时间段由多个单位时间累积而成,所以说并发的多个任务在单位时间内不一定同时在执行。在单CPU的时代多个任务都是并发执行的,这是因为单个CPU同时只能执行一个任务。原创 2024-09-13 10:45:18 · 860 阅读 · 0 评论 -
JAVA线程基础二——原子性操作
使用 synchronized 关键字的确可以实现线程安全性,即内存可见性和原子性,但是synchronized 是独占锁,没有获取内部锁的线程会被阻塞掉,而这里的 getCount 方法只是读操作,多个线程同时调用不会存在线程安全问题。答案是肯定的,下面将讲到的在内部使用非阻塞CAS算法实现的原子性操作类AtomicLong 就是一个不错的选择。所谓原子性操作,是指执行一系列操作时,这些操作要么全部执行,要么全部不执行不存在只执行其中一部分的情况。那么如何才能保证多个操作的原子性呢?原创 2024-09-14 10:35:06 · 352 阅读 · 0 评论 -
JAVA线程基础二——CAS 操作
敬请期待。原创 2024-09-14 10:33:59 · 111 阅读 · 0 评论 -
JAVA线程基础二——CAS 实现(Unsafe类)
JDK的rt.jar 包中的 Unsafe 类提供了硬件级别的原子性操作,Unsafe 类中的方法都是native 方法,它们使用JNI的方式访问本地C++实现库。下面我们来了解一下 Unsafe 提供的几个主要的方法以及编程时如何使用 Unsafe 类做一些事情。下面是JDK8新增的函数,这里只列出 Long 类型操作。原创 2024-09-20 10:47:57 · 1029 阅读 · 0 评论 -
JAVA线程基础二——Java 指令重排序
答案是不一定,由于代码(1)(2)(3)(4)之间不存在依赖关系,所以写线程的代码(3)(4)可能被重排序为先执行(4)再执行(3),那么执行(4)后,读线程可能已经执行了(1)操作,并且在(3)执行前开始执行(2)操作,这时候输出结果为 0 而不是 4。在如上代码中,变量c的值依赖a和b的值,所以重排序后能够保证(3)的操作在(2)(1)之后,但是(1)(2)谁先执行就不一定了,这在单线程下不会存在问题,因为并不影响最终结果。原创 2024-09-20 11:39:44 · 438 阅读 · 0 评论 -
JAVA线程基础二——伪共享
当CPU访问某个变量时,首先会去看CPUCache内是否有该变量,如果有则直接从中获取,否则就去主内存里面获取该变量,然后把该变量所在内存区域的一个Cache 行大小的内存复制到 Cache 中。由于存放到Cache 行的是内存块而不是单个变量,所以可能会把多个变量存放到一个Cache行中。在该图中,变量x和y同时被放到了CPU的一级和二级缓存,当线程1使用CPU1对变量x进行更新时,首先会修改CPU1的一级缓存变量x所在的缓存行,这时候在缓存一致性协议下,CPU2中变量x对应的缓存行失效。原创 2024-09-20 11:49:00 · 281 阅读 · 0 评论 -
JAVA线程基础二——锁的概述之乐观锁与悲观锁
当一个线程要获取一个被其他线程持有的独占锁时,该线程会被阻塞,那么当一个线程再次获取它自己已经获取的锁时是否会被阻塞呢?如果不被阻塞,那么我们说该锁是可重入的,也就是只要该线程获取了该锁,那么可以无限次数(在高级中我们将知道,严格来说是有限次数)地进入被该锁锁住的代码。下面看一个例子,看看在什么情况下会使用可重入锁。在如上代码中,调用 helloB 方法前会先获取内置锁,然后打印输出。之后调用helloA方法,在调用前会先去获取内置锁,如果内置锁不是可重入的,那么调用线程将会一直被阻塞。原创 2024-09-25 12:14:05 · 1110 阅读 · 0 评论 -
JAVA并发编程高级——JAVA并发包中ThreadLocalRandom类原理剖析
本文章首先讲解了 Random的实现原理以及Random 在多线程下需要竞争种子原子变量更新操作的缺点,从而引出ThreadLocalRandom类。ThreadLocalRandom 使用 ThreadLocal的原理,让每个线程都持有一个本地的种子变量,该种子变量只有在使用随机数时才会被初始化。在多线程下计算新种子时是根据自己线程内维护的种子变量进行更新,从而避免了竞争。原创 2024-09-27 12:11:52 · 1111 阅读 · 0 评论