![](https://img-blog.csdnimg.cn/20201014180756780.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
并发编程
文章平均质量分 88
每天都得进步
一个小学生
展开
-
十、详解ReentrantReadWriteLock读写锁
之前我们讲过可重入锁从这篇博文中我们可以了解到,基于lock的锁底层都是利用aqs这个抽象类的。那么在读写锁中,其本质也是利用aqs,与可重入锁之间的区别的就是在实现抽象方法的时候,具体的逻辑不一样。可以理解为两者骨架一样,但是具体细节逻辑有区别,尤其是在tryAcquire和tryRelease的逻辑不一样。原创 2023-12-28 16:00:24 · 886 阅读 · 1 评论 -
八、详解CAS无锁
在之前的文章中,我们详细讲过了Synchronized和ReentrantLock的原理,以及他们如何实现线程安全的。但是在这两种方式种,都是在不满足条件的时候将当前线程阻塞,直到被另一个线程唤醒。这两种方式都需要切换线程上下文,而线程切换将消耗大量资源。jdk提供了一种无锁的方式来保证线程之间安全。即循环CAS。原创 2023-12-20 16:01:52 · 1283 阅读 · 1 评论 -
九、详解线程池ThreadPool
有图可知,线程池的核心组成部分分别为:线程列表和阻塞队列。1、线程列表:这个很容易理解,就是一堆线程,用一个列表存储起来。每次都复用列表中的线程来执行任务,而不需要重新创建新的线程。2、阻塞队列:为什么需要一个阻塞队列呢,普通的队列行不行呢?之所以阻塞队列,主要的原因是平衡【放任务】和【拿任务】之间的速率。如果【放任务】的速度快,但是【拿任务】的速度慢,那么就需要一个队列来存储多余的任务。原创 2023-12-25 17:22:43 · 891 阅读 · 0 评论 -
七、详解Volatile
volatile是Java提供的一种轻量级的同步机制,它主要有两个特性:保证变量的可见性和禁止指令重排序。1. 保证变量的可见性:在Java中,为了提高效率,每个线程都会有自己的工作内存(可以理解为CPU的高速缓存),线程对变量的所有操作都会在工作内存中进行,然后再同步回主内存。如果一个变量被volatile修饰,那么当一个线程修改了这个变量后,新的值会立即同步回主内存,当其他线程需要读取这个变量时,会直接从主内存中读取,而不是从工作内存,这样就保证了变量的可见性。原创 2023-12-19 20:13:18 · 776 阅读 · 0 评论 -
六、三种方式实现线程交替打印
要求:给定三个线程A,B,C。要求A,B,C三个线程一次打印a,b,c。原创 2023-12-19 17:56:16 · 429 阅读 · 0 评论 -
五、详解ReentrantLock
哲学家只有在拿到左右两边的筷子后才能吃面,吃完后再把筷子放下,继续思考。这个问题的关键在于,如果每位哲学家都先拿起自己左边的筷子,然后等待右边的筷子,那么就会出现死锁的情况,因为每位哲学家都在等待别人放下筷子,但是没有人会放下筷子。死锁是指两个或多个线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力干涉,它们都将无法继续执行下去。2、尝试加锁:利用trylock的思想,先拿起一根筷子,然后尝试拿下一个筷子,如果拿到了就吃饭,如果拿不到,就释放所有的筷子。原创 2023-12-18 22:07:49 · 414 阅读 · 0 评论 -
四、wait-notify
wait-notify必须配合synchronized,并且为重量级锁。await-signal必须配合lock。原创 2023-12-18 18:26:12 · 393 阅读 · 0 评论 -
三、详解Synchronized
为了解决这个问题,我们可以把修改变量的代码放在临界区内,这样在同一时刻只有一个线程能够修改这个变量,从而避免了数据不一致的问题。在Java中,我们可以使用synchronized关键字或者Lock接口来创建临界区。临界区是多线程编程中的一个术语,指的是一个访问共享资源的代码区域,这个区域不能被多个线程同时执行。也就是说,在同一时刻,只能有一个线程执行临界区的代码。临界区主要用于处理多线程环境下的竞态条件,防止数据不一致的问题。例如,当两个线程同时修改同一个变量时,就可能会出现竞态条件,导致数据不一致。原创 2023-12-15 16:54:33 · 906 阅读 · 0 评论 -
二、线程创建与运行
这个target就是run()方法中调用的target对象,也就是我们传递的Runnable对象。在方式1中,我们直接复写run方法,那么当线程运行的时候自然会直接执行我们复写的run方法,这个很好理解。我们看一下Thread的run方法。在java中通过继承Thread类,或者直接new一个Thread类来创建一个线程。通过实现一个Runnalbe接口,将此接口传递给Thread类,来创建一个线程。其实本质上线程池的方式也是利用上述两种方式来创建具体的对象。线程真正执行的逻辑就是run方法的逻辑。原创 2023-12-15 12:30:11 · 50 阅读 · 0 评论 -
一、并发基础知识
当一个任务在执行时,如果它需要等待另一个任务完成(例如等待I/O操作或者等待其他任务的结果),那么这个任务就会被阻塞,直到它所依赖的任务完成为止。但是,在等待操作完成的过程中,线程是被阻塞的。并发任务之间可能并不是真正同时执行的,例如,在单核处理器的系统中,虽然在任何给定的单一时刻只有一个任务在执行,但是由于任务之间的切换速度非常快,使得人们感觉它们似乎在同时执行。线程相比于进程,具有更小的资源占用,更快的创建和结束速度,以及更高的并发性,因此在需要大量并发操作,或者需要更高效率的场合,会使用多线程编程。原创 2023-12-15 11:41:07 · 1061 阅读 · 0 评论