当前位置:网站首页 > 技术博客 > 正文

java并发编程实战和并发编程的艺术



JAVA并发系列文章

  1. 【JAVA】:万字长篇带你了解JAVA并发编程【一】-CSDN博客
  2. 【JAVA】:万字长篇带你了解JAVA并发编程-线程池【二】-CSDN博客
  3. 【JAVA】:万字长篇带你了解JAVA并发编程-并发集合【三】-CSDN博客
  4. 【JAVA】:万字长篇带你了解JAVA并发编程-线程安全【四】-CSDN博客
  5. 【JAVA】:万字长篇带你了解JAVA并发编程-并发设计模式【五】-CSDN博客
  6. 【JAVA】:万字长篇带你了解JAVA并发编程-死锁优化【六】-CSDN博客

并发与并行

是在不同实体上的多个事件,是在同一实体上的多个事件。

不过这种解释非常晦涩难懂,对于基础和涉世未深的开发人员可能来说如同天书一样。

那我们就回溯本源,来讲一下他们的区别。

并发(Concurrency)

早期计算机的 CPU 都是单核的,一个 CPU 在同一时间只能执行一个进程/线程(任务),当系统中有多个进程/线程任务等待执行时,CPU 只能执行完一个再执行下一个。
计算机在运行过程中,有很多指令会涉及 I/O 操作,而 I/O 操作又是相当耗时的,速度远远低于 CPU,这导致 CPU 经常处于空闲状态,只能等待 I/O 操作完成后才能继续执行后面的指令。
为了提高 CPU 利用率,减少等待时间,人们提出了一种 CPU 并发工作的理论。

所以谈起并发,我们可以想象成,一条质检员(CPU)想要质检多条流水线(线程/进程)的物品(任务)。这个工人来回在多个生产线上质检货品的操作就是.

将 CPU 资源合理地分配给多个任务共同使用,有效避免了 CPU 被某个任务长期霸占的问题,极大地提升了 CPU 资源利用率。

并行(Parallelism)

并发是针对单核 CPU 提出的,而并行则是针对多核 CPU 提出的。和单核 CPU 不同,多核 CPU 真正实现了“同时执行多个任务”。

多核 CPU 的每个核心都可以独立地执行一个任务,而且多个核心之间不会相互干扰。在不同核心上执行的多个任务,是真正地同时运行,这种状态就叫做。

并发针对单核 CPU 而言,它指的是 CPU 交替执行不同任务的能力;并行针对多核 CPU 而言,它指的是多个核心同时执行多个任务的能力。
单核 CPU 只能并发,无法并行;换句话说,并行只可能发生在多核 CPU 中。
在多核 CPU 中,并发和并行一般都会同时存在,它们都是提高 CPU 处理任务能力的重要手段。

线程与进程

【JAVA】多线程:一文快速了解多线程

线程的状态与生命周期

【JAVA】多线程:一文快速了解多线程

线程同步与锁

:是指在多线程中,为了保证线程安全,使得一组线程按照一定的顺序执行,不会出现竞态条件。在Java中,可以使用关键字实现同步。

❤️‍🔥 一文让你看懂并发编程中的锁

准备:多线程测试工具类

 

synchronized关键字

  • 互斥性(共享锁)
  • 可重入
 

加载代码块中

 

ReentrantLock

相对于 它具备如下特点

  • 可中断
  • 可以设置超时时间
  • 可以设置为公平锁
  • 支持多个条件变量
  • 与 synchronized 一样,都支持可重入

ReentrantLock是可重入的互斥锁,虽然具有与synchronized相同功能,但是会比synchronized更加灵活

基本语法
 
可中断

和 的锁, 是不可被打断的; 也就是说别的线程已经获得了锁, 线程就需要一直等待下去,不能中断,直到获得到锁才运行。

一个线程等待锁的时候,是可以被中断。通过中断异常报出。处理中断使其继续执行逻辑

 
设置超时时间 tryLock()

使用 lock.tryLock() 方法会返回获取锁是否成功。如果成功则返回true,反之则返回false。

并且tryLock方法可以设置指定等待时间,参数为:tryLock(long timeout, TimeUnit unit) , 其中timeout为最长等待时间,TimeUnit为时间单位

获取锁的过程中, 如果超过等待时间, 或者被打断, 就直接从阻塞队列移除, 此时获取锁就失败了, 不会一直阻塞着 ! (可以用来实现死锁问题)

tryLock适合我们再预期判断是否可以获得锁的前提下进行业务处理。而不需要一直等待,占用线程资源。

当我们tryLock的时候,表示我们试着获取锁,如果已经被其他线程占用,那么就可以直接跳过处理,提示用户资源被处理中。

 

结果:

 
公平锁 new ReentrantLock(true)

k默认是, 可以指定为公平锁。
在线程获取锁失败,进入阻塞队列时,先进入的会在锁被释放后先获得锁。这样的获取方式就是公平的。
一般不设置ReentrantLock为公平的, 会降低并发度.
Synchronized底层的Monitor锁就是不公平的, 和谁先进入阻塞队列是没有关系的。

条件变量 Condition

使用流程

  1. 前需要 获得
  2. await 执行后,会释放锁,进入 conditionObject (条件变量)中等待
  3. await 的线程被唤醒(或打断、或超时)取重新竞争 lock 锁
  4. 竞争 lock 锁成功后,从 await 后继续执行
  5. signal 方法用来唤醒条件变量(等待室)汇总的某一个等待的线程
  6. signalAll方法, 唤醒条件变量(休息室)中的所有线程
 

ReadWriteLock

ReadWriteLock也是一个接口,提供了readLock和writeLock两种锁的操作机制,一个资源可以被多个线程同时读,或者被一个线程写,但是不能同时存在读和写线程。

读锁:共享锁 readLock

写锁: 独占锁 writeLock

读写锁一定要注意几点。

  1. 一定要记得读锁和写锁之间的竞争关系。只有读锁与读锁之间是不存在竞争,其他都会产生锁竞争,锁阻塞。
  2. 对于读锁而言,由于同一时刻可以允许多个线程访问共享资源,进行读操作,因此称它为共享锁;而对于写锁而言,同一时刻只允许一个线程访问共享资源,进行写操作,因此称它为排他锁。
  3. 记住锁的通用范式,一定要释放锁
 

CountDownLatch

例子: 游戏加载资源

只有5个资源线程同时加载完成,游戏才能开始

 

CyclicBarrier

CyclicBarrier可以理解为一个循环栅栏,其实和CountDownLatch有一定的相同点。就是都是需要进行计数,CyclicBarrier是等待所有人都准备就绪了,才会进行下一步。不同点在于,CyclicBarrier结束了一次计数之后会自动开始下一次计数。而CountDownLatch只能完成一次。

 

CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程使用await()方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。

CyclicBarrier的另一个构造函数CyclicBarrier(int parties, Runnable barrierAction),用于线程到达屏障时,优先执行barrierAction,方便处理更复杂的业务场景。

await方法

调用await方法的线程告诉CyclicBarrier自己已经到达同步点,然后当前线程被阻塞。直到parties个参与线程调用了await方法,CyclicBarrier同样提供带超时时间的await和不带超时时间的await方法

 

Semaphore

Semaphore主要是用来控制资源数量的工具,可以理解为信号量。
初始化时给定信号量的个数,其他线程可以来尝试获得许可,当完成任务之后需要释放响应的许可。
这样同时并行/并发处理的数量最大为我们指定的数量。约束住同时访问资源的数量限制。

 

Exchanger

Exchanger是一个用于线程间协作的工具类。它提供了一个交换的同步点,在这个交换点两个线程能够交换数据。具体交换数据的方式是通过exchange函数实现的,如果一个线程先执行exchange函数,那么它会等待另一个线程也执行exchange方法。当两个线程都到达了同步交换点,两个线程就可以交换数据。

两个人同时到达指定的地点,然后留下信息,exchanger把信息交换传输。

 

Phaser

是新引入的,我们可以将Phaser的概念看成是一个个的阶段, 每个阶段都需要执行的线程任务,任务执行完毕后就进入下一阶段。这里和CyclicBarrier 和CountDownLatch的概念类似, 实际上也确实可以用Phaser代替CyclicBarrier和CountDownLatch。

Phaser也是通过计数器来控制, 在Phaser中叫parties, 我们在指定了parties之后, Phaser可以根据需要动态增加或减少parties的值

 

并发针对单核 CPU 而言,它指的是 CPU 交替执行不同任务的能力;并行针对多核 CPU 而言,它指的是多个核心同时执行多个任务的能力。
单核 CPU 只能并发,无法并行;换句话说,并行只可能发生在多核 CPU 中。
在多核 CPU 中,并发和并行一般都会同时存在,它们都是提高 CPU 处理任务能力的重要手段。

  • 上一篇: layer获取弹出层
  • 下一篇: sql语句编写技巧
  • 版权声明


    相关文章:

  • layer获取弹出层2024-11-10 18:30:02
  • 数据库有哪些?2024-11-10 18:30:02
  • 已有的vue项目如何改造成ssr2024-11-10 18:30:02
  • 金字塔组织结构2024-11-10 18:30:02
  • matlab如何创建一个函数文件2024-11-10 18:30:02
  • sql语句编写技巧2024-11-10 18:30:02
  • 霍夫曼树代码2024-11-10 18:30:02
  • 2021免费dns2024-11-10 18:30:02
  • 破除压缩文件密码2024-11-10 18:30:02
  • 进程和线程对应关系2024-11-10 18:30:02