并发编程基础
在并发编程中,需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体)。
线程间通信
通信是指线程之间以何种机制来交换 信息。 在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递。
共享内存
在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写 - 读内 存中的公共状态来隐式进行通信。
消息传递
在消息传递的并发模型里,线程之间没有公共状态,线程之间必须通过明确的发送消息来显式进行通信。
同步
同步是指程序用于控制不同线程之间操作发生相对顺序的机制。
共享内存
在共享内存并发模 型里,同步是显式进行的。 程序员必须显式指定某个方法或某段代码需要在线程之间互斥执行。
消息传递
在消息传递的并发模型里,由于消息的发送必须在消息的接收之前, 因此同步是隐式进行的。
#java的内存模型 Java 的并发采用的是共享内存模型,Java 线程之间的通信总是隐式进行,整个通信过程对程序员完全透明。
在 java 中,所有实例域、 静态域和数组元素存储在堆内存中,堆内存在线程之间共享。
局部变量 ( Local variables ) , 方法定义参数( java 语言规范称之为 formal method parameters ) 和异常处理器参数( exception handler parameters ) 不会在线程之间 共享,它们不会有内存可见性问题,也不受内存模型的影响。
Java 线程之间的通信由 Java 内存模型, (简称为 JMM )控制。
#happens-before
为了让应用程序能够免于数据竞争的干扰,Java 5 引入了明确定义的 Java 内存模型。其中最为重要的一个概念便是 happens-before 关系。happens-before 关系是用来描述两个操作的内存可见性的。如果操作 X happens-before 操作 Y,那么 X 的结果对于 Y 可见。
线程内的happens-before
在同一个线程中,字节码的先后顺序(program order)也暗含了 happens-before 关系:在程序控制流路径中靠前的字节码 happens-before 靠后的字节码。然而,这并不意味着前者一定在后者之前执行。实际上,如果后者没有观测前者的运行结果,即后者没有数据依赖于前者,那么它们可能会被重排序。
线程间happens-before
除了线程内的 happens-before 关系之外,Java 内存模型还定义了下述线程间的 happens-before 关系。
1、解锁操作 happens-before 之后(这里指时钟顺序先后)对同一把锁的加锁操作。 2、volatile 字段的写操作 happens-before 之后(这里指时钟顺序先后)对同一字段的读操作。 3、线程的启动操作(即 Thread.starts()) happens-before 该线程的第一个操作。 4、线程的最后一个操作 happens-before 它的终止事件(即其他线程通过 Thread.isAlive() 或 Thread.join() 判断该线程是否中止)。 5、线程对其他线程的中断操作 happens-before 被中断线程所收到的中断事件(即被中断线程的 InterruptedException 异常,或者第三个线程针对被中断线程的 Thread.interrupted 或者 Thread.isInterrupted 调用)。 6、构造器中的最后一个操作 happens-before 析构器的第一个操作。
参考文章:gk.link/a/11V4M