【Java并发编程的艺术学习】第三章摘要补全

第三章整篇依旧围绕写后读这一核心,本文章目的是为更好的了解学习,所以会添加一些必须了解的知识,同样也会对文章重要内容进行摘要。

3.1Java内存模型的基础

1.线程之间如何通信

方式一:使用 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博客

2.进程之间如何通信

管道

管道本质上就是内核中的一个缓存,当进程创建一个管道后,Linux会返回两个文件描述符,一个是写入端的描述符,一个是输出端的描述符,可以通过这两个描述符往管道写入或者读取数据。

如果想要实现两个进程通过管道来通信,则需要让创建管道的进程fork子进程,这样子进程们就拥有了父进程的文件描述符,这样子进程之间也就有了对同一管道的操作。
消息队列

A进程往消息队列写入数据后就可以正常返回,B进程需要时再去读取就可以了,效率比较高。

而且,数据会被分为一个一个的数据单元,称为消息体,消息发送方和接收方约定好消息体的数据类型,不像管道是无格式的字节流类型,这样的好处是可以边发送边接收,而不需要等待完整的数据。

共享内存

不同的进程拿出一块虚拟内存空间,映射到相同的物理内存空间。这样一个进程写入的东西,另一个进程马上就能够看到,不需要进行拷贝。

信号量

信号

Socket
 

原文链接:进程间的通信方式(六种)_进程间通信-CSDN博客

3.显式:人为

隐式:非人为

4.什么是happens-before

在Java中,如果一个操作happens-before另一个操作,那么第一个操作的结果将对第二个操作可见,即第二个操作可以看到第一个操作的影响。

3.2重排序

1.发生以下情况就不可以重排序

2.as-if-serial语句的意思

不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变。编译器、runtime和处理器都必须遵守as-if-serial语义

3.3顺序一致性

1.什么是事务

多次操作,具有原子特征,对于这一系列操作要么都成功要么都失败

3.6final

1.final的工作量较volatile轻一些,所以在部分场景下final比volatile快

2.final防止指令重排序

3.8双重检查锁定与延迟初始化

1.枚举类只有一个对象,当枚举类第一次用到的时候就存在于内存中

2.单例模式:一个类中只有一个对象

3.实现单例模式的方式:枚举(最简单的方式),懒加载(使用时加载)

枚举缺点:一加载进内存它的对象就存在,所以内存消耗比较大

4.该代码来源于菜鸟教程 单例模式 | 菜鸟教程 (runoob.com)
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语句还有一个作用,当时间片再次轮到该进程时,其他线程想通过该方法时会发现该对象已经被上锁

后续:写的很菜,有错误的话希望大佬指出,上面附带的原文转载写的都很不错,我把这个彻底弄明白了会再写一版,各位都加油

  • 48
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值