分类: C/C++
2012-12-23 14:41:40
线程安全定义:
我们可以从多个方面来定义线程安全
1. 从代码的角度来定义:我们说一段代码是线程安全的,指的是当多个线程同时调用这段代码时,这段代码操作的共享资源(数据结构和行为)不会处于一个不安全的中间状态,所有线程都有一个或一组可预期的操作结果。
2. 从数据结构的角度来定义:我们说某个数据结构的访问时线程安全的,是指当多个线程从不同的角度来访问它的对象或者实例时,它不会处于一个不安全的中间状态。而是对任何线程,都有一个或一组可预期的结果。
很多时候,我们会根据不同的需求来处理线程安全,或者根据我们使用的编程语言来决定如何处理线程安全。
比如,为了性能,我们可能不设计一个线程安全的数据结构,而是把它的线程安全放到线程代码中去,更有甚者,我们会从系统的角度来限制某些操作的时机,已达到对它访问的线程安全。
比如,为了用户编程的便捷性,或者使某个类库可以被应用在多种运行环境中,我们往往不在类库中定义线程安全的类,而是让使用者根据他们的实际情况在库外处理线程安全的问题。
比如,在C中,我们基本上是在线程代码中去处理共享资源的线程安全的,这是因为它的行为和数据不能被定义在一起。在C++中,我们更偏向在类中处理线程安全,那么访问这个类对象的线程代码就不需要处理线程安全的问题了。
也许你会说,在C中,我们可以定义一组访问结构对象的函数,然后所有对这个结构对象的访问都必须通过这组函数来实现,这样我们也可以达到和C++类似的设计目的。这就是C和C++的最大区别,有没有发现我划掉了“必须”这两个字?在C中,它没有关键字来定义“必须”。而在C++中,它提供了一组关键字给类的设计者,让设计者告诉用户,你必须做什么,否则你不能实现你想做的。
所以在面向对象的语言中,我们有了一个新概念:线程安全的class。
那么一个线程安全的class应该满足什么条件呢?
(《Java并发编程实践》)
无论定义如何,我们的核心目标都是如何使共享资源在多线程环境下可以被安全的访问。而如何设计一个实用高效的线程安全的代码和数据结构,并不是很容易的事情。需要很多的经验积累。
比如经典的:嵌套锁,必须按照相同的顺序加锁解锁。
下面,我们将一起来看看如何处理一些经典的线程安全问题。