我想知道当一个应用程序中的三个线程(几乎)同时从 DLL 调用静态方法时会发生什么。是否为每个线程加载了 3 个 DLL 实例,或者其他线程是否只有在第一个线程使用 DLL 静态方法完成后才能访问 DLL(即)每个线程一旦轮到它就可以访问 dll?
3 回答
是否加载了 3 个 DLL 实例,每个线程一个?
不会。DLL通常每个进程加载一次。(这里有一些微妙的问题;如果你使用Load
and ,同一个程序集可能会被加载两次LoadFrom
。但这是一种罕见的情况,与线程无关。)
是否只有在第一个线程使用 DLL 静态方法完成后才能访问 DLL?
不; 静态方法不会自动序列化。如果您需要该方法来确保一次只有一个线程访问它,那么您将不得不自己编写代码来执行此操作。
静态构造函数的行为确实有点像这样。运行时将确保“赢得比赛”的线程将运行静态构造函数。其他线程将等待第一个线程完成 cctor。有关详细信息,请阅读我最近的系列文章。
通常,代码会被加载一次,即使对于非静态对象也是如此。
您必须担心 的是声明变量(统称为state )中包含的信息,而不是代码。
DLL 仅在内存中加载一次。
如果同一进程中有多个线程调用或访问 DLL 中的全局变量,则 DLL 必须通过使用临界区保护对全局/共享数据的访问来保证线程安全。
如果有来自多个进程的多个线程访问 DLL,只要访问同一个 DLL 的进程的线程不超过一个,线程安全就不是问题。
操作系统巧妙地管理内存,使得最初它只从代码和数据部分的一份副本开始。数据部分页面以只读方式映射。当需要在其中一个进程中修改任何全局数据时,操作系统会出现分段错误并创建页面的副本并将其映射为进程的内存空间中的可写。这种方法称为写时复制。