前言目前正在出一个长期的Java多线程系列教程,从入门到高级包括源码解读,篇幅会更长,如果你喜欢就点个关注吧??~本文内容:纯理论和一点并发编程模型我们之前给大家讲过一些关于多线程的知识。首先我们要知道,在并发编程模型下,会遇到两大问题:线程之间如何通信并发模型的问题主要有两种:消息传递模型共享内存模型那么它们是如何解决的呢?消息传递模型如何通信?线程之间没有共同的状态,它们必须通过发送消息来显式通信。如何同步?消息传递本质上是同步的,因此共享内存模型如何通信是隐含的?程序的publicstate是线程间共享的,如何通过内存中读写publicstate来同步隐式通信?需要显示指定线程之间的互斥。Java中使用的第二种方法是共享内存并发模型。Java内存模型结构。首先说一下运行时数据区,主要分为两类线程共享区,主要包括方法区。而堆的线程私有区主要包括虚拟机栈、本地方法栈、程序计数器。对于每个线程来说,栈是私有的,堆是共享的,所以栈中的变量,比如局部变量,方法定义参数,Exceptionhandler参数,都是不共享的,所以内存是不可见的,所以不受影响通过内存模型,堆中的变量是共享的,所以也叫共享变量。内存可见性是针对共享变量的堆是否必须可见?堆也有内存不可见的问题。它是怎么发生的?这是因为现代计算机为了提高效率,经常将共享变量缓存在缓存区,因为CPU访问缓存区比访问内存快得多。所谓内存不可见,就是当一个线程在自己的缓冲区中有一个共享变量的副本时,对于主存中共享变量的值是不可见的,看不到主存中的值。线程在操作共享变量时,首先从主存中拉取并复制一个变量到自己的工作内存中,然后修改工作内存中的变量,处理完成后将工作内存中的值重写回主存。所以在这个过程中,如果恰好在缓存过期前命中,就会导致更新后的主存中值不一致的问题。在Java中,每个线程都有自己的本地内存,存放线程供读写共享。变量的副本是一个抽象的概念。线程之间的通信由内存模型控制,简称JMM。所有共享变量都存储在主存储器中。每个线程都保留一份该线程使用的共享变量的副本。因此,“线程间通信必须通过主存”,JMM规定“线程对共享变量的所有操作都必须在自己的本地内存中进行,不能直接从主存中读取”。Java中的volatile关键字可以保证共享变量在多线程操作中的可见性,禁止指令重排序。synchronized关键字既保证了可见性,又保证了原子性(互斥)。在较低级别,JMM实现内存可见性并禁止通过内存屏障重新排序。为了方便程序员,提出了happens-before,更简单易懂,避免了程序员为了理解内存可见性而去学习复杂的重排序规则和这些规则的具体实现方法。结束语这一段的内容可能没有之前那么容易理解,比较抽象,所以这篇文章也有不足之处。大家可以自己多查一些资料,全面了解一下。
