Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
实现比线程提供更好隔离但性能相当的Linux并发原语是否可行?_Linux_Multithreading_Concurrency_Ipc - Fatal编程技术网

实现比线程提供更好隔离但性能相当的Linux并发原语是否可行?

实现比线程提供更好隔离但性能相当的Linux并发原语是否可行?,linux,multithreading,concurrency,ipc,Linux,Multithreading,Concurrency,Ipc,考虑以下应用程序:一个web搜索服务器,它在启动时根据从磁盘读取的数据创建一个大的网页内存索引。一旦初始化,就不能修改内存中的索引,并且启动多个线程来服务用户查询。假设服务器编译为本机代码并使用OS线程 现在,线程模型不提供线程之间的隔离。有缺陷的线程或任何非线程安全代码都可能损坏由其他线程分配并在逻辑上属于其他线程的索引或内存。这些问题很难检测和调试 理论上,Linux允许实施更好的隔离。一旦索引初始化,它所占用的内存就可以标记为只读。线程可以替换为共享索引(共享内存)但不是具有单独堆且不能相

考虑以下应用程序:一个web搜索服务器,它在启动时根据从磁盘读取的数据创建一个大的网页内存索引。一旦初始化,就不能修改内存中的索引,并且启动多个线程来服务用户查询。假设服务器编译为本机代码并使用OS线程

现在,线程模型不提供线程之间的隔离。有缺陷的线程或任何非线程安全代码都可能损坏由其他线程分配并在逻辑上属于其他线程的索引或内存。这些问题很难检测和调试

理论上,Linux允许实施更好的隔离。一旦索引初始化,它所占用的内存就可以标记为只读。线程可以替换为共享索引(共享内存)但不是具有单独堆且不能相互损坏的进程。非法操作由硬件和操作系统自动检测。不需要互斥体或其他同步原语。与内存相关的数据竞争被完全消除


这种模式在实践中是否可行?您是否知道有任何实际应用程序可以做这些事情?或者可能有一些根本性的困难使得这种模式不切实际?您认为与传统线程相比,这种方法会带来性能开销吗?从理论上讲,所使用的内存是相同的,但是是否存在一些与实现相关的问题会使事情变得更慢?

我认为您可能会发现一些有趣的问题。此外,您还可以创建共享内存并以只读方式打开它,然后创建线程。这应该不会导致性能下降

您可以使用
mprotect()
将索引设置为只读。在64位系统上,您可以将每个线程的本地内存映射到一个随机地址(请参阅),这使得一个线程与另一个线程发生内存损坏的几率非常小(当然,任何完全丢失映射内存的损坏都会导致segfault)。显然,每个线程都需要有不同的堆。

显而易见的解决方案是根本不使用线程。使用单独的流程。由于每个进程与代码和只读结构有很多共同之处,因此共享只读数据非常简单:根据需要在文件中格式化以供内存使用,并将文件映射到内存


使用此方案,只有每个过程数据的变量是独立的。代码将被共享,静态初始化的数据将被共享,直到写入。如果一个过程嘎嘎作响,对其他过程没有影响。根本没有并发问题。

肯定有应用程序使用mmap将各种内存空间标记为只读。然而,这通常是出于性能原因,而不是为了防止错误代码。虽然我当然不想发动宗教战争,但改用支持真正不可变类型的语言(如Java)将解决“损坏内存”的“错误线程”的许多问题.多线程程序中的内存损坏不仅发生在线程写入内存中的随机位置(此类错误相对容易避免和检测)时,而且发生在线程获得对非线程安全且被其他线程使用的对象的有效引用时。此类错误更难预防和检测,并且可能发生在任何多线程程序中,无论使用何种语言。线程是否具有不同的堆,或者不同的堆是否区分线程和进程?堆就是
malloc
获取内存的地方。要给不同的线程提供不同的堆,只需要从不同的池中提取每个线程(使用特定于线程的数据)。你只需要使用正确的malloc库和正确的选项,问题是堆随机化的想法只会防止一类错误——由于对随机位置的写入而导致的内存损坏。正如我在其他评论中所写的,这样的bug相对更容易预防和检测。更大的问题是完全隔离将完全消除的数据竞争。假设一个线程调用一个函数,该函数返回指向非线程安全静态对象的指针。如果其他线程调用相同的函数,则存在数据竞争,并且返回的指针随机化也无济于事。没有猜测到指针是通过有效调用获得的。@JanWrobel:从你的问题中我不明白你想避免编写线程安全代码。