调制信号识别系列 (一):基准模型

调制信号识别系列 (一):基准模型

说明:本文包含对CNN和CNN+LSTM基准模型的复现,模型架构参考下述两篇文章

文章目录

  • 调制信号识别系列 (一):基准模型
    • 一、论文
      • 1、DL-PR: Generalized automatic modulation classification method based on deep learning with priori regularization
      • 2、A Deep Learning Approach for Modulation Recognition via Exploiting Temporal Correlations
    • 二、流程
      • 1、数据加载
      • 2、训练测试
      • 3、可视化
    • 三、模型
      • 1、CNN
      • 2、CNN+LSTM(DL-PR)
      • 3、CNN+LSTM
    • 四、对比
      • 1、论文1
      • 2、论文2
    • 五、总结

一、论文

1、DL-PR: Generalized automatic modulation classification method based on deep learning with priori regularization

  • https://www.sciencedirect.com/science/article/pii/S095219762300266X

image-20240707105742936

image-20240706174502716

2、A Deep Learning Approach for Modulation Recognition via Exploiting Temporal Correlations

  • 2018 IEEE 19th International Workshop on Signal Processing Advances in Wireless Communications (SPAWC)

  • https://ieeexplore.ieee.org/abstract/document/8445938

image-20240707114714838

Note that before each convolutional layer, we use the zero-padding method to control the spatial size of the output volumes. Specifically, we pad the input volume with two zeros around the border, thus the output volume of the second convolutional layer is of size 32 × 132. We then take 32 as the dimensionality of the input and 132 as the time steps in LSTM layer. Dropout method is also used to prevent the neural network from overfitting. Compared to architecture in [12], we can see that we replace the third dense fully-connected layer with a LSTM layer. Our simulations suggest that this replacement not only reduces the number of parameters by an order of magnitude, but also leads to a significant performance improvement.

请注意,在每个卷积层之前,我们使用零填充方法来控制输出卷的空间大小。具体来说,我们在输入量的边界周围填充两个零,因此第二个卷积层的输出量的大小为 32 × 132。然后我们将 32 作为输入的维度,将 132 作为 LSTM 层的时间步长。 Dropout方法也用于防止神经网络过拟合。与[12]中的架构相比,我们可以看到我们用 LSTM 层替换了第三个密集全连接层。我们的模拟表明,这种替换不仅将参数数量减少了一个数量级,而且还带来了显着的性能改进。

二、流程

1、数据加载

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset, random_split
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
from torchsummary import summary
# 加载数据
csv_file_path = 'snr_data/output_data_snr_6.csv'
data_frame = pd.read_csv(csv_file_path)# 提取前256列数据并转换为张量
vectors = torch.tensor(data_frame.iloc[:, :256].values, dtype=torch.float32)# 将256维向量转换为2x128的矩阵形式
vectors = vectors.view(-1, 2, 128)# 划分训练集和测试集索引
train_size = int(0.8 * len(vectors))
test_size = len(vectors) - train_size
train_indices, test_indices = random_split(range(len(vectors)), [train_size, test_size])# 使用训练集的统计量进行归一化
train_vectors = vectors[train_indices]# 对IQ分量分别进行归一化
train_mean_I = train_vectors[:, 0, :].mean(dim=0, keepdim=True)
train_std_I = train_vectors[:, 0, :].std(dim=0, keepdim=True)train_mean_Q = train_vectors[:, 1, :].mean(dim=0, keepdim=True)
train_std_Q = train_vectors[:, 1, :].std(dim=0, keepdim=True)# 归一化整个数据集
vectors[:, 0, :] = (vectors[:, 0, :] - train_mean_I) / train_std_I
vectors[:, 1, :] = (vectors[:, 1, :] - train_mean_Q) / train_std_Q# 提取Mod_Type列并转换为数值标签
mod_types = data_frame['Mod_Type'].astype('category').cat.codes.values
labels = torch.tensor(mod_types, dtype=torch.long)# 创建TensorDataset
dataset = TensorDataset(vectors, labels)# 创建训练集和测试集
train_dataset = TensorDataset(vectors[train_indices], labels[train_indices])
test_dataset = TensorDataset(vectors[test_indices], labels[test_indices])# 创建DataLoader
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)
# 替换模型架构

2、训练测试

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
num_epochs = 50
train_losses = []
test_losses = []
train_accuracies = []
test_accuracies = []def calculate_accuracy(outputs, labels):_, predicted = torch.max(outputs, 1)total = labels.size(0)correct = (predicted == labels).sum().item()return correct / totalfor epoch in range(num_epochs):# 训练阶段model.train()running_loss = 0.0correct = 0total = 0for inputs, labels in train_loader:inputs = inputs.to(device)labels = labels.to(device)optimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()running_loss += loss.item()correct += (outputs.argmax(1) == labels).sum().item()total += labels.size(0)train_loss = running_loss / len(train_loader)train_accuracy = correct / totaltrain_losses.append(train_loss)train_accuracies.append(train_accuracy)# 测试阶段model.eval()running_loss = 0.0correct = 0total = 0with torch.no_grad():for inputs, labels in test_loader:inputs = inputs.to(device)labels = labels.to(device)outputs = model(inputs)loss = criterion(outputs, labels)running_loss += loss.item()correct += (outputs.argmax(1) == labels).sum().item()total += labels.size(0)test_loss = running_loss / len(test_loader)test_accuracy = correct / totaltest_losses.append(test_loss)test_accuracies.append(test_accuracy)print(f"Epoch [{epoch+1}/{num_epochs}], Train Loss: {train_loss:.4f}, Train Accuracy: {train_accuracy:.4f}, Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.4f}")print("Training complete.")

3、可视化

epochs = range(1, num_epochs + 1)plt.figure(figsize=(12, 5))# 绘制损失图像
plt.subplot(1, 2, 1)
plt.plot(epochs, train_losses, label='Train Loss')
plt.plot(epochs, test_losses, label='Test Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.title('Loss vs. Epochs')# 绘制准确率图像
plt.subplot(1, 2, 2)
plt.plot(epochs, train_accuracies, label='Train Accuracy')
plt.plot(epochs, test_accuracies, label='Test Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
plt.title('Accuracy vs. Epochs')plt.show()

三、模型

说明:下述模型均在SNR=6dB RadioML2016.10a数据集下的实验结果,仅使用原始的IQ分量信息,未使用数据增强,也未进行调参

1、CNN

class CNNModel(nn.Module):def __init__(self):super(CNNModel, self).__init__()self.conv1 = nn.Conv2d(1, 64, (1, 4), stride=1)self.conv2 = nn.Conv2d(64, 64, (1, 2), stride=1)self.pool1 = nn.MaxPool2d((1, 2))self.conv3 = nn.Conv2d(64, 128, (1, 2), stride=1)self.conv4 = nn.Conv2d(128, 128, (2, 2), stride=1)self.pool2 = nn.MaxPool2d((1, 2))self.conv5 = nn.Conv2d(128, 256, (1, 2), stride=1)self.conv6 = nn.Conv2d(256, 256, (1, 2), stride=1)self.fc1 = nn.Linear(256 * 1 * 28, 512)self.fc2 = nn.Linear(512, 128)self.fc3 = nn.Linear(128, 11)def forward(self, x):x = x.unsqueeze(1)  # 添加通道维度x = torch.relu(self.conv1(x))x = torch.relu(self.conv2(x))x = self.pool1(x)x = torch.relu(self.conv3(x))x = torch.relu(self.conv4(x))x = self.pool2(x)x = torch.relu(self.conv5(x))x = torch.relu(self.conv6(x))x = x.view(x.size(0), -1)x = torch.relu(self.fc1(x))x = torch.relu(self.fc2(x))x = self.fc3(x)return xmodel = CNNModel()
summary(model, (2, 128))

image-20240707115545394

----------------------------------------------------------------Layer (type)               Output Shape         Param #
================================================================Conv2d-1           [-1, 64, 2, 125]             320Conv2d-2           [-1, 64, 2, 124]           8,256MaxPool2d-3            [-1, 64, 2, 62]               0Conv2d-4           [-1, 128, 2, 61]          16,512Conv2d-5           [-1, 128, 1, 60]          65,664MaxPool2d-6           [-1, 128, 1, 30]               0Conv2d-7           [-1, 256, 1, 29]          65,792Conv2d-8           [-1, 256, 1, 28]         131,328Linear-9                  [-1, 512]       3,670,528Linear-10                  [-1, 128]          65,664Linear-11                   [-1, 11]           1,419
================================================================
Total params: 4,025,483
Trainable params: 4,025,483
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.00
Forward/backward pass size (MB): 0.63
Params size (MB): 15.36
Estimated Total Size (MB): 15.98

image-20240707115320324

image-20240707115331410

2、CNN+LSTM(DL-PR)

import torch
import torch.nn as nnclass CNNLSTMModel(nn.Module):def __init__(self):super(CNNLSTMModel, self).__init__()self.conv1 = nn.Conv2d(1, 32, (2, 3), stride=1, padding=(0,1))  # Adjusted input channels and filtersself.conv2 = nn.Conv2d(32, 32, (1, 3), stride=1, padding=(0,1))self.pool1 = nn.MaxPool2d((1, 2))self.conv3 = nn.Conv2d(32, 64, (1, 3), stride=1, padding=(0,1))self.conv4 = nn.Conv2d(64, 64, (1, 3), stride=1, padding=(0,1))self.pool2 = nn.MaxPool2d((1, 2))self.conv5 = nn.Conv2d(64, 128, (1, 3), stride=1, padding=(0,1))self.conv6 = nn.Conv2d(128, 128, (1, 3), stride=1, padding=(0,1))self.pool3 = nn.MaxPool2d((1, 2))self.lstm = nn.LSTM(128, 32, batch_first=True)  # Adjusted input size and LSTM hidden sizeself.fc1 = nn.Linear(32, 128)self.fc2 = nn.Linear(128, 11)def forward(self, x):#print("x:",x.shape)if x.dim() == 3:x = x.unsqueeze(1)  # 假设x的形状是[2, 128], 这将改变它为[1, 2, 128]#print("x.unsqueeze(0):",x.shape)x = torch.relu(self.conv1(x))x = torch.relu(self.conv2(x))x = self.pool1(x)x = torch.relu(self.conv3(x))x = torch.relu(self.conv4(x))x = self.pool2(x)x = torch.relu(self.conv5(x))x = torch.relu(self.conv6(x))x = self.pool3(x)# Prepare input for LSTMx = x.view(x.size(0), 16, 128)  # Adjusted view#print(x.shape)x, (hn, cn) = self.lstm(x)x = x[:, -1, :]  # Get the last output of the LSTMx = torch.relu(self.fc1(x))x = self.fc2(x)return xmodel = CNNLSTMModel()
summary(model,input_size=(1, 2, 128))

image-20240707115501540

==========================================================================================
Layer (type:depth-idx)                   Output Shape              Param #
==========================================================================================
CNNLSTMModel                             [1, 11]                   --
├─Conv2d: 1-1                            [1, 32, 1, 128]           224
├─Conv2d: 1-2                            [1, 32, 1, 128]           3,104
├─MaxPool2d: 1-3                         [1, 32, 1, 64]            --
├─Conv2d: 1-4                            [1, 64, 1, 64]            6,208
├─Conv2d: 1-5                            [1, 64, 1, 64]            12,352
├─MaxPool2d: 1-6                         [1, 64, 1, 32]            --
├─Conv2d: 1-7                            [1, 128, 1, 32]           24,704
├─Conv2d: 1-8                            [1, 128, 1, 32]           49,280
├─MaxPool2d: 1-9                         [1, 128, 1, 16]           --
├─LSTM: 1-10                             [1, 16, 32]               20,736
├─Linear: 1-11                           [1, 128]                  4,224
├─Linear: 1-12                           [1, 11]                   1,419
==========================================================================================
Total params: 122,251
Trainable params: 122,251
Non-trainable params: 0
Total mult-adds (M): 4.32
==========================================================================================
Input size (MB): 0.00
Forward/backward pass size (MB): 0.20
Params size (MB): 0.49
Estimated Total Size (MB): 0.69
==========================================================================================

image-20240707115432051

image-20240707115443808

3、CNN+LSTM

# 定义结合CNN和LSTM的模型
class CNNLSTMModel(nn.Module):def __init__(self):super(CNNLSTMModel, self).__init__()self.conv1 = nn.Conv2d(1, 64, (1, 4), stride=1)self.conv2 = nn.Conv2d(64, 64, (1, 2), stride=1)self.pool1 = nn.MaxPool2d((1, 2))self.conv3 = nn.Conv2d(64, 128, (1, 2), stride=1)self.conv4 = nn.Conv2d(128, 128, (2, 2), stride=1)self.pool2 = nn.MaxPool2d((1, 2))self.conv5 = nn.Conv2d(128, 256, (1, 2), stride=1)self.conv6 = nn.Conv2d(256, 256, (1, 2), stride=1)self.lstm = nn.LSTM(256, 128, batch_first=True)self.fc1 = nn.Linear(128, 512)self.fc2 = nn.Linear(512, 128)self.fc3 = nn.Linear(128, 11)def forward(self, x):x = x.unsqueeze(1)  # 添加通道维度x = torch.relu(self.conv1(x))x = torch.relu(self.conv2(x))x = self.pool1(x)x = torch.relu(self.conv3(x))x = torch.relu(self.conv4(x))x = self.pool2(x)x = torch.relu(self.conv5(x))x = torch.relu(self.conv6(x))# 重新调整x的形状以适应LSTMx = x.squeeze(2).permute(0, 2, 1)  # 变为(batch_size, 128, 256)# 通过LSTMx, _ = self.lstm(x)# 取最后一个时间步的输出x = x[:, -1, :]# 全连接层x = torch.relu(self.fc1(x))x = torch.relu(self.fc2(x))x = self.fc3(x)return x
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = CNNLSTMModel().to(device)
summary(model,input_size=(1, 2, 128))

image-20240707115530202

==========================================================================================
Layer (type:depth-idx)                   Output Shape              Param #
==========================================================================================
CNNLSTMModel                             [1, 11]                   --
├─Conv2d: 1-1                            [1, 64, 2, 125]           320
├─Conv2d: 1-2                            [1, 64, 2, 124]           8,256
├─MaxPool2d: 1-3                         [1, 64, 2, 62]            --
├─Conv2d: 1-4                            [1, 128, 2, 61]           16,512
├─Conv2d: 1-5                            [1, 128, 1, 60]           65,664
├─MaxPool2d: 1-6                         [1, 128, 1, 30]           --
├─Conv2d: 1-7                            [1, 256, 1, 29]           65,792
├─Conv2d: 1-8                            [1, 256, 1, 28]           131,328
├─LSTM: 1-9                              [1, 28, 128]              197,632
├─Linear: 1-10                           [1, 512]                  66,048
├─Linear: 1-11                           [1, 128]                  65,664
├─Linear: 1-12                           [1, 11]                   1,419
==========================================================================================
Total params: 618,635
Trainable params: 618,635
Non-trainable params: 0
Total mult-adds (M): 19.33
==========================================================================================
Input size (MB): 0.00
Forward/backward pass size (MB): 0.59
Params size (MB): 2.47
Estimated Total Size (MB): 3.07
==========================================================================================

image-20240707115355065

image-20240707115406360

四、对比

1、论文1

image-20240707120612759

image-20240707120737565

本文的实验结果和论文1的结果比较类似,即使without priori regularization

2、论文2

image-20240707120151123

image-20240707120316218

五、总结

  • 对于RadioML2016.10a数据集来说,在信噪比不是特别低的情况下,使用CNN就表现的不错,在SNR=6dB可达91.82%,但是这里有个小技巧,在卷积过程中,先单独对IQ分量进行卷积,在convolution 4进行联合处理,一开始就使用2x2的卷积核效果较差。

image-20240707121309134

  • 实验结果表明,CNN+LSTM 优于 CNN,但涨幅不多

image-20240707121937158

image-20240707121959303

  • 完整的代码和数据集在GIthub:https://github.com/daetz-coder/RadioML2016.10a_Benchmark,为了方便使用,IQ分量保存在csv中,且仅提供了SNR=6dB的数据,如果需要更多类型的数据,请参考https://blog.csdn.net/a_student_2020/article/details/139800725

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/41228.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件架构之操作系统

第 2 章操作系统 本章主要介绍操作系统的基本概念及其形成、发展历史和主要类型,并指出操作系统的5 大管理功能。掌握操作系统原理的关键在于深入理解“一个观点、两条线索”。一个观点是以资源管理的观点来定义操作系统;两条线索是指操作系统如何管理计…

【计算机毕业设计】020基于weixin小程序订餐系统

🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板&#xff…

C语言获取当前时间

一共有两段代码&#xff0c;一个是获取当前时间&#xff0c;一个是获取到现在的总毫秒数 求关注&#x1f604; 互粉必回 获取当前时间 #include <stdio.h> #include <time.h> int main() { time_t rawtime; struct tm * timeinfo; char buffer[20]; // 获取当前…

Linux内核编译与调试menuos-linux-3.18.6-在ubuntu20.04环境

1 具体操作 下载 linux-3.18.6内核 wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.18.6.tar.xz解压进入linux-3.18.6文件夹 tar -xvf linux-3.18.6.tar.xz cd linux-3.18.6/编译 #make x86_64_defconfig # 为x86_64生成配置 #make alldefconfig make i3…

每天一个数据分析题(四百零十)- 主成分

实际应用中&#xff0c;关于主成分数量K的取值&#xff0c;下列说法错误的是&#xff08; &#xff09; A. 可以基于碎石图进行判断 B. 特征根从大到小排序&#xff0c;通常要求前 K 个特征根都大于 1 C. 通常要求 K 个主成分的累积方差比超过 80% D. 各个主成分之间的方向…

什么是区块链的“智能合约”

区块链的“智能合约”是一种存储在区块链上的计算机协议&#xff0c;它能够自动执行合约条款&#xff0c;并在满足预设条件时自动执行相关操作。智能合约通过编程语言&#xff08;如Solidity&#xff09;编写&#xff0c;可以在去中心化的环境中运行&#xff0c;无需人工干预。…

spdlog一个非常好用的C++日志库(七): 源码分析之异常类spdlog_ex

目录 1.自定义异常类spdlog_ex 1.1.通用异常 1.2.系统调用异常 1.3.what()函数 2.异常的使用 2.1.抛出异常 2.2.控制异常使用 1.自定义异常类spdlog_ex 标准库异常类&#xff08;std::exception&#xff09;系列&#xff0c;能满足大多数使用异常的场景&#xff0c;但对…

100359.统计X和Y频数相等的子矩阵数量

1.题目描述 给你一个二维字符矩阵 grid&#xff0c;其中 grid[i][j] 可能是 X、Y 或 .&#xff0c;返回满足以下条件的子矩阵数量&#xff1a; 包含 grid[0][0]X 和 Y 的频数相等。至少包含一个 X。 示例 1&#xff1a; 输入&#xff1a; grid [["X","Y",…

Avalonia中的样式

文章目录 前言样式定义代码切换样式样式主题前言 Avalonia的样式是Styles,与WPF类似。用于在控件之间共享属性设置用于在控件之间共享属性设置,样式由 Selector和属性组成。 样式定义 下面定义一个最简单的样式 <Window.Styles><Style Selector="TextBlock…

双 Token 无感刷新机制实现

✅作者简介&#xff1a;热爱Java后端开发的一名学习者&#xff0c;大家可以跟我一起讨论各种问题喔。 &#x1f34e;个人主页&#xff1a;Hhzzy99 &#x1f34a;个人信条&#xff1a;坚持就是胜利&#xff01; &#x1f49e;当前专栏&#xff1a;项目实践 &#x1f96d;本文内容…

微信小程序性能与体验优化

1. 合理的设置可点击元素的响应区域大小&#xff1b; 比较常见的是页面的点击按钮太小&#xff0c;用户点击不到按钮&#xff0c;这样用户体验很不好。 2. 避免渲染页面耗时过长&#xff1b; 当页面渲染时间过长的话&#xff0c;会让用户感觉非常卡顿&#xff0c;当出现这种…

密室逃脱——收集版修改测试

一、原版修改 1、导入资源 Unity Learn | 3D Beginner: Complete Project | URP 2、设置Scene 删除SampleScene&#xff0c;打开UnityTechnologies-3DBeginnerComplete下的MainScene 3、降低音量 (1) 打开Hierarchy面板上的Audio降低音量 (2) 打开Prefabs文件夹&#xf…

lnmp php7 安装ssh2扩展

安装ssh2扩展前必须安装libssh2包 下载地址: wget http://www.libssh2.org/download/libssh2-1.11.0.tar.gzwget http://pecl.php.net/get/ssh2-1.4.tgz &#xff08;这里要换成最新的版本&#xff09; 先安装 libssh2 再安装 SSH2: tar -zxvf libssh2-1.11.0.tar.gzcd libss…

若依框架(RuoYi)中实现部门及子部门用户查询的SQL逻辑解析

前言 在基于若依框架&#xff08;RuoYi&#xff09;的项目开发中&#xff0c;经常会遇到需要根据部门ID查询其下属所有用户的需求&#xff0c;包括直接隶属于该部门的用户以及属于其子部门的所有用户。这一需求在组织架构管理、权限分配等场景中尤为常见。本文将深入解析一段典…

【深入理解计算机系统——2信息的表示和处理】

计算机的本质就是二进制&#xff0c;0/1&#xff0c;称之为bit&#xff08;位&#xff09;&#xff0c;一个位没有什么意义&#xff0c;当同时拥有多个位&#xff0c;并且加上某种解释&#xff0c;就可以表示任何有限集合的元素。&#xff08;为什么是有限&#xff1f;因为用bi…

【日志信息管理】管理日志信息的类

日志用于记录程序的执行记录包括程序的出错记录&#xff0c;程序致命退出原因&#xff0c;程序的正常执行记录。这样我们就可以很快的察觉程序的错误原因、执行状况等等&#xff0c;因此管理日志信息是非常重要的。 日志一般由以下部分组合&#xff1a; 日志时间、日志等级、…

Java 基础--File - IO流(2)

I/O流 定义 数据从硬盘流向内存为输入流&#xff0c;数据从内存流向硬盘为输出流。输入也叫读取数据&#xff0c;输出也叫写出数据。 IO分类 1.按照数据的流向分为&#xff1a;输入流和输出流 ①输入流&#xff1a;把数据从其他设备上读取到内存中的流 ②输出流&#xff1…

Qt 基础组件速学 事件过滤器

学习目标&#xff1a;理解事件过滤器 前置环境 运行环境:qt creator 4.12 学习内容和效果演示&#xff1a; Qt 提供了事件过滤器的机制,允许我们在事件到达目标对象之前对事件进行拦截和处理。这在以下情况下非常有用: 全局事件处理: 我们可以在应用程序级别安装一个事件过…

工控人最爱的PLC触摸屏一体机,有多香

PLC触摸屏一体机是什么 PLC触摸屏一体机&#xff0c;听起来可能有点技术化&#xff0c;但简单来说&#xff0c;它就是一个集成了可编程逻辑控制器&#xff08;PLC&#xff09;和触摸屏的智能设备。这种设备不仅能够执行自动化控制任务&#xff0c;还能实时显示和操作设备状态&a…

JVM原理(十九):JVM虚拟机内存模型

1. 硬件的效率与一致性 数据不安全的原因&#xff1a;缓存一致性的问题 共享内存多核系统&#xff1a;在多路处理器系统中&#xff0c;每个处理器都有自己的高速缓存&#xff0c;而他们又共享同一主内存。 线程先后执行结果不一致问题&#xff1a;除了增加高速缓存之外&#…