1.常见的会引起资源冲突的
·文件系统资源:多个线程同时读取,写入或删除同一文件或目录时
·数据库资源: 多线程并发访问和修改同一数据库记录(缺乏事务控制或锁定机制),多个线程或进程使用数据库连接资源时,可能导致连接超时或连接耗尽。
·内存资源: 多线程同时访问或修改静态(全局)变量时可能引发竞争条件,导致数据不一致出错
·网络资源:同时范文或操作同一个网络套接字(如发送和接受数据)可能会引发冲突,导致数据包丢失或混乱;多个进程绑定同一端口等;
·硬件资源:多线程同时访问打印机,扫描仪可能会引起冲突。
·配置文件: 多线程同时读取或写入同一配置文件
·日志文件:多线程同时写入同一个日志文件
2.常用的解决资源冲突的方法
内存映射文件(内容映射到进程的虚拟地址中)、临时文件缓存(本地副本文件)、内存流(内存中(堆)划一块区域存储临时文件)
//防止资源占用,使用内存流存储数据byte[] pixels;int width, height;using (Bitmap bitmap = new Bitmap(patientMsg.PicturePath)){width = bitmap.Width; // 保存宽度信息height = bitmap.Height; // 保存高度信息using (MemoryStream ms = new MemoryStream()){bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); // 将图片保存到内存流pixels = ms.ToArray(); // 将图片数据转换为字节数组,传输和存储本地等方便,需要再转为bitmap}}MemoryByteBuffer buffer = new MemoryByteBuffer(pixels);
适用场景:文件系统资源
访问非常大的文件(如图像文件),如果是很小的文件,用锁就行了
通过async和await实现异步网络操作,在不阻塞主线程的情况下处理多个网络请求
适用场景: 网络资源,数据库资源
对于数据库资源可能存在的高并发访问的场景,应该使用数据库连接池会更好
在Program.cs 配置// 添加DbContext服务,配置连接池,可以应对高并发services.AddDbContextPool<AppDbContext>(options =>options.UseSqlServer(connectionString));// 添加DbContext服务,不配置连接池services.AddDbContext<AppDbContext>(options =>options.UseSqlServer(connectionString));
适用场景:数据库资源
EFCore是实现了优秀的连接池管理
使用各种锁(互斥锁,读写锁)来禁止多线程同时访问同一资源
static int sharedResource = 0;static readonly object mutex = new object();static void Increment(){for (int i = 0; i < 10000; i++){lock (mutex){sharedResource++;}}}
适用场景:内存资源
锁内的执行步骤应该较为简单,且执行不需要耗费太长时间。
单例模式只有一个全局实例负责配置文件的操作,从而避免多个实例同时访问配置文件可能带来的竞争问题。
public class DicomLogger{private static readonly Lazy<DicomLogger> instance = new Lazy<DicomLogger>(() => new DicomLogger());private string logFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs", "log.txt");//路径private DicomLogger(){string logDirectory = Path.GetDirectoryName(logFilePath);if (!Directory.Exists(logDirectory)){Directory.CreateDirectory(logDirectory);}Log.Logger = new LoggerConfiguration().MinimumLevel.Information().WriteTo.RollingFile(logFilePath).CreateLogger();}}public class DicomConfigurationManager{private static readonly Lazy<DicomConfigurationManager> instance = new Lazy<DicomConfigurationManager>(() => new DicomConfigurationManager()); //仅首次访问instance实例化private DicomConfigData configData;private string pacsConfigFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PacsConfig.ini");private readonly object _lock = new object();private DicomConfigurationManager(){configData = LoadConfiguration() ?? new DicomConfigData();}}
适用场景:硬件资源、配置文件、日志文件
注意单例的实现方式。