《C++面向对象高效编程(第2版)》——2.20 什么是多线程安全类-阿里云开发者社区

开发者社区> 异步社区> 正文

《C++面向对象高效编程(第2版)》——2.20 什么是多线程安全类

简介:
+关注继续查看

本节书摘来自异步社区出版社《C++面向对象高效编程(第2版)》一书中的第章,第2.20节,作者: 【美】Kayshav Dattatri,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.20 什么是多线程安全类

C++面向对象高效编程(第2版)
传统上,操作系统(OS)只支持进程(也称为任务)。每个进程都有自己的地址空间,且有一个单独的执行线程,进程执行一个包含一系列指令的程序。但是,现在大多数操作系统都支持单进程中的多线程。一个任务可根据需要包含多个线程,单进程中的所有线程共享进程的地址空间,线程可以访问进程中的所有全局数据。

使用线程有很多优点。首先,创建线程的成本更低(且更效率)。创建一个新进程需要涉及操作系统中的大量工作(设置内存页面、注册、进程上下文等),而线程需要的大多数资源都可以从进程中获得。其次,线程间的通信更加容易。不同的进程位于不同的地址空间中,因此进程之间的通信(IPC)并不容易。但是,在单个进程中,不同的线程共享相同的地址空间,因此线程之间的通信非常容易。另外,在多线程中,可以阻止(block)操作,也可以并行处理操作。操作系统单独调度(schedule)每一个线程。例如,有一个应用程序,允许从一个设备上复制文件到另一个设备上,用户可能要求在中途停止复制操作。如果创建一个仅用于等待用户输入的单独进程,显然很不合理。在这种情况下,创建一个等待用户输入的单独线程更加合适。主应用程序执行复制操作,而辅助线程等待用户输入。如果用户决定终止复制操作,则运行等待用户输入的线程,并通知主应用程序,用户要求中止操作;然后,主应用程序线程中止复制操作。在单个应用程序中使用多线程非常普遍。再举另外一例,文档处理应用程序可以用一个线程打印文档,而另一个线程执行生成索引,同时还有另一个线程用于接收用户提供的文档摘要信息。

任何使用多线程的应用程序都可称为多线程应用程序。涉及多个线程时,同步(synchronization)和互斥(mutual exclusion)尤为重要。当一个线程正在访问某段数据时(例如,打印文档的线程),必须防止其他线程试图访问相同的数据(为了写入)。根据操作系统,实现可以使用互斥体(mutex)、信号量(semaphore)、临界区(crical section)、自旋锁定(spin-lock)、消息、事件等来达到这个目的。例如,文档中的每一页都由一个互斥体来保护,只允许一个线程访问该页。无论用何种访问控制的方案,实现必须确保不会发生死锁(deadlock)情况。

应用程序(或系统)在多线程运行的环境中正常运行称为多线程安全(multi-thread safe)。确保多线程安全并不容易,实现必须使用之前提及的某种同步方案来实现互斥。

我们在这里讨论的并不是新内容,只有在涉及多进程时,同步才是个问题。不管怎样,一个进程不能访问另一个进程地址空间内的内容,这使得同步稍微容易一些。但是,进程中的线程共享进程所拥有的资源。因此,确保适当的同步非常重要。例如,在文档处理的应用程序中,如果打印线程已锁定页面,索引线程在访问相同页面之前必须等待,直到打印线程解锁页面。

在使用引用计数(reference counting)(也称为使用计数(use count))方案的情况下,多线程安全非常关键。引用计数方案将在后续章节中讨论。修改引用计数必须是一个线程安全的操作。

在多线程环境中使用对象时,多线程安全更加重要。如果不能确保多线程安全,可能会导致灾难。一个进程内的两个线程可以使用相同的对象。记住,所有对象都共享成员函数代码。当一个线程调用一个成员函数,在成员函数内部完成执行之前,如果(操作系统)调度(schedule)另一个线程运行,且该线程也通过相同的对象调用相同的成员函数,则对象必须保证自身完整和运行良好。如果对象不能做到这一点,这样的类就不是线程安全(thread-safe)的。当然,如果一个类(成员函数和数据成员)没有任何线程安全的特殊要求,维持线程安全就完全不成问题。

在设计新的类时,注意多线程安全非常重要。如果类的对象即使在多线程环境下都能保持完整,必须在类的文档中予以说明。另一方面,如果类的对象不保证多线程安全,也要在类的头文件和文档中清楚地说明其局限性。不要误认为设计的每个类都必须保证多线程安全,事实并非如此。是否需要线程安全取决于类和客户的要求。还需记住,X类如果使用其他类作为它实现的一部分,为保证X类为线程安全,有必要保证它使用的其他类都为线程安全。或者,即使它所依赖的其他类非线程安全,至少必须保证X类线程安全(这更加困难)。为达到线程安全,下面列举了一些指导原则:

(1)如果类声明为线程安全,确保每个成员函数实现也是线程安全的。

(2)如果类在实现中使用其他的类(对象),确保仍然能保证线程安全。

(3)如果使用一些类库来实现类,确保正在使用的库函数是线程安全的。

(4)如果正在使用操作系统调用,检查以确保这些调用都是线程安全的。

(5)当使用编译器提供的库时,检查它们是否都是线程安全的。

许多库的供应商提供辅助类,用于帮助达到线程安全。例如,查看提供线程安全引用计数的类十分常见。如果你的项目需要线程安全,它可能会帮助实现一组确保线程安全的低级类。这样的类可以提供引用计数、线程安全指针、线程安全打印实用程序等。如果整个项目小组都在各自的实现中使用这些类,就能保证整个项目的线程安全。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
网站安全检测对帝国CMS代码的后台功能性安全测试
最近我们SINE安全在对帝国CMS系统进行代码安全审计的时候,发现该系统存在网站漏洞,受影响的版本是EmpireCMS V7.5,从帝国官方网站下载到本地,我们人工对其代码进行详细的漏洞检测与安全代码分析。
2278 0
借助ThreadLocal实现多线程安全 | 带你学《Java语言高级特性》之三十二
本节结合消息发送案例简单直白地向读者展现了多线程模式下的线程安全问题,并向读者介绍了ThreadLocal类及其实现线程安全的原理,讲解了其使用方法。
881 0
java多线程 --ConcurrentLinkedQueue 非阻塞 线程安全队列
ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部;当我们获取一个元素时,它会返回队列头部的元素。
994 0
java安全编码指南之:线程安全规则
如果我们在多线程中引入了共享变量,那么我们就需要考虑一下多线程下线程安全的问题了。那么我们在编写代码的过程中,需要注意哪些线程安全的问题呢?
2655 0
【高并发】终于弄懂为什么局部变量是线程安全的了!!
相信很多小伙伴都知道局部变量是线程安全的,那你知道为什么局部变量是线程安全的吗?
22 0
Servlet实例数量到底多少,是否线程安全
通过注解或servlet声明都能控制 servlet 容器如何提供 servlet 实例。
4 0
浅析多线程的对象锁和Class锁
一、前言 本来想在另外一篇文章说的,发现可能篇幅有点大,所以还是另开一篇博文来说好了。知识参考《Java多线程编程核心技术》,评价下这本书吧——大量的代码,简单的说明,真像在看博客。不过这本书浅显易懂,篇幅也不长,一口气看个几十页,再照着demo敲敲代码,简直不要太爽。
682 0
+关注
异步社区
异步社区(www.epubit.com)是人民邮电出版社旗下IT专业图书旗舰社区,也是国内领先的IT专业图书社区,致力于优质学习内容的出版和分享,实现了纸书电子书的同步上架,于2015年8月上线运营。公众号【异步图书】,每日赠送异步新书。
12049
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载