Java并发编程的艺术(三)

Java并发编程的艺术(三)

线程是如何进行通信的?

  • 通过共享内存:通过共享内存的读写操作进行隐式的通信
  • 通过消息传递:没有共享内存时,就需要显示的发送消息来进行通信

线程是如何同步的呢?

首先同步是指程序中用于控制不同线程间操作发生相对顺序的机制。
  • 通过共享内存:需要通过对共享内存加锁进行线程间互斥来显示地进行线程同步。
  • 通过消息传递:因为消息发送一定在消息接收之前,所以是隐式的进行了线程同步。
    Java的并发采用的是共享内存模型,Java线程之间的通信总是隐式进行,整个通信过程对程序员完全透明。

jVM的内存结构

 线程共享的内存区域:实例、静态变量、数组对象。
  • java是通过JMM(内存模型)来控制线程间通信的: 它决定一个线程对共享变量的写入何时对另一个线程可见。因为每个线程都会在本地内存中保存一份共享内存的副本,所以线程间通信是需要线程A先将自己的修改存入到主存中,然后线程B读取该共享内存数据。因此。JMM通过控制线程跟主存之间的交互来为Java程序员提供内存可见性保证。
  • 数据依赖性:如果两个操作同时访问一个变量,且这个两个操作中存在写操作,就会产生数据依赖性。
  • as-is-serial:不管怎么重排序,单线程(程序)运行的结果是不能改变的。
  • 顺序一致性:程序执行的结果与程序在顺序一致性内存模型中执行的结果一致。

从源码到指令序列的重排列

编译器和处理器为了提高程序性能进行优化的一种方式。
  • 编译期优化重排序:在程序编译期间,会在不影响单线程语义的情况下,调整语句的执行顺序。
  • 指令级并行重排序:现代处理器采用了指令级并行技术IPL来将多条指令重叠执行。如果不存在数据依赖,处理器可以改变语句对应机器指令的执行顺序。
  • 内存系统重排序:由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。

上述的1属于编译器重排序,2和3属于处理器重排序。因为重排序可能会导致多线程出现内存可见性的问题:

  1. 对于编译器重排序:JMM的编译器重排序规则会禁止特定类型的编译器重排序。
  2. 对于处理器的重排序:JMM的处理器重排序规则会要求Java编译器在生成指令序列时,插入特定类型的内存屏障(Memory Barriers,Intel称之为Memory Fence)指令,通过内存屏障指令来禁止特定类型的处理器重排序。

Happens-Before:先行发生原则

是判断数据是否存在竞争,线程是否安全的主要依据。

在JMM中,如果一个操作的结果需要对另一个操作可见,那么这两个操作之间必须要存在happens-before关系(并不是在它之前执行,只是结果对其可见)。它具有四个规则:

  • 程序顺序规则:一个线程中的每个操作都happens-before它后面的任意操作
  • 监视器锁规则:对一个锁的解锁要happens-before对它加锁之前
  • volatile规则:对一个volatile变量的写要happens-before于任意后续对他的读。
  • 对象终结原则:一个对象的初始化先行于其finalize()方法
  • 传递性

ReentrantLock:可重入锁

  • 可重入,因为是手动加锁释放锁,所以要保证加锁和释放锁的次数一样多。
  • 可以响应中断(Sychronized不可以响应中断,一个线程获取不到锁就一直堵塞等待)
  • 可以尝试获取锁:trylock()
  • 可以实现公平锁,但默认是非公平锁。公平锁指在锁上等待时间最长的线程将获得锁的使用权。
    锁的实现过程:
    1. 公平锁和非公平锁的所释放都会写一个volatile变量state;
    2. 公平锁在获取锁的时候会读取volatile的变量;而非公平锁在获取锁的时候会利用CAS更新一次volatile变量state的值;

因此锁的内存语义一般有两种形式:1)利用volatile变量的读写; 2)利用CAS附带的volatile内存读写的语义。

concurrent包的实现

  1. 首先,声明共享变量为volatile。
  2. 使用CAS的原子条件更新来实现线程之间的同步。
  3. 配合以volatile的读/写和CAS所具有的volatile读和写的内存语义来实现线程之间的通信。

final域的内存语义

  • 写final域的重排序规则禁止把final域的写重排序到构造函数之外。
  • 初次读一个包含final域的对象的引用,域随后初次读这个final域,这两个操作之间不能重排序
  • 在构造函数返回前,被构造对象的引用不能为其他线程所见
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值