第三章整篇依旧围绕写后读这一核心,本文章目的是为更好的了解学习,所以会添加一些必须了解的知识,同样也会对文章重要内容进行摘要。
方式一:使用 volatile 关键字
基于 volatile 关键字来实现线程间相互通信是使用共享内存的思想,大致意思就是多个线程同时监听一个变量,当这个变量发生变化的时候 ,线程能够感知并执行相应的业务。这也是最简单的一种实现方式。
方式二:使用Object类的wait() 和 notify() 方法
Object类提供了线程间通信的方法:wait()、notify()、notifyaAl(),它们是多线程通信的基础,而这种实现方式的思想自然是线程间通信。注意: wait和 notify、notifyaAl必须配合synchronized使用,wait方法释放锁,notify方法不释放锁
方式三:使用JUC工具类 CountDownLatch
jdk1.5之后在java.util.concurrent包下提供了很多并发编程相关的工具类,简化了我们的并发编程代码的书写,CountDownLatch基于AQS框架,相当于也是维护了一个线程间共享变量state
方式四:使用 ReentrantLock 结合 Condition
方式五:基本LockSupport实现线程间的阻塞和唤醒
LockSupport 是一种非常灵活的实现线程间阻塞和唤醒的工具,使用它不用关注是等待线程先进行还是唤醒线程先运行,但是得知道线程的名字。
原文链接:线程之间的通信方式_线程通信-CSDN博客
管道
管道本质上就是内核中的一个缓存,当进程创建一个管道后,Linux会返回两个文件描述符,一个是写入端的描述符,一个是输出端的描述符,可以通过这两个描述符往管道写入或者读取数据。
如果想要实现两个进程通过管道来通信,则需要让创建管道的进程fork子进程,这样子进程们就拥有了父进程的文件描述符,这样子进程之间也就有了对同一管道的操作。
消息队列
A进程往消息队列写入数据后就可以正常返回,B进程需要时再去读取就可以了,效率比较高。
而且,数据会被分为一个一个的数据单元,称为消息体,消息发送方和接收方约定好消息体的数据类型,不像管道是无格式的字节流类型,这样的好处是可以边发送边接收,而不需要等待完整的数据。
共享内存
不同的进程拿出一块虚拟内存空间,映射到相同的物理内存空间。这样一个进程写入的东西,另一个进程马上就能够看到,不需要进行拷贝。
信号量
信号
Socket
原文链接:进程间的通信方式(六种)_进程间通信-CSDN博客
隐式:非人为
在Java中,如果一个操作happens-before另一个操作,那么第一个操作的结果将对第二个操作可见,即第二个操作可以看到第一个操作的影响。
多次操作,具有原子特征,对于这一系列操作要么都成功要么都失败
1.final的工作量较volatile轻一些,所以在部分场景下final比volatile快
2.final防止指令重排序
1.枚举类只有一个对象,当枚举类第一次用到的时候就存在于内存中
2.单例模式:一个类中只有一个对象
3.实现单例模式的方式:枚举(最简单的方式),懒加载(使用时加载)
枚举缺点:一加载进内存它的对象就存在,所以内存消耗比较大
public class Singleton {
private volatile static Singleton singleton; //该语句中volatile含义:第一个线程成功创建对象时值可能为空,没有的话后续其他线程知道不及时可能进入阻塞队列,有则保证其他线程及时知道不为空防止进入阻塞队列。
//这个为什么是静态?静态方法只能操作静态对象,所以受下面静态方法影响,该语句只能是静态的。
private Singleton (){} //构造方法私有代表不允许创建对象,其他线程不允许new
public static Singleton getSingleton() { //每个线程只能通过这个方法访问对象,为什么这个方法是静态的?因为非静态方法需要创建对象,而在这段代码中是不允许创建对象的
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
执行过程:假设此时有n个线程想使用该对象,通过getSingleton方法,首先判断第一个if语句
此时该对象没有被上锁,if判断为true进入下一步
此时进入8个恰好时间片到了,那么(x-4)个留在外面,4个进入执行下一步
对类进行加锁
第二个if再次判断,发现类已经被上锁,拦截剩下三个并进入阻塞队列
第一个拿到对象
第一个if语句还有一个作用,当时间片再次轮到该进程时,其他线程想通过该方法时会发现该对象已经被上锁
后续:写的很菜,有错误的话希望大佬指出,上面附带的原文转载写的都很不错,我把这个彻底弄明白了会再写一版,各位都加油