一起来学POSIX thread 之 不变量、临界区、谓词
1、不变量(invariant)
所谓的不变量是由程序作出的假设,特别是有关变量组间关系的假设。当编写队列包时,你需要为每一个队列指定一个队列头指针,指向队列的第一个元素。每一个数据元素也包含指向下一个元素的指针。重要的并不完全是数据,程序还要依赖于数据之间的关系。例如,队列或者为空,或者包含一个指向队首元素的指针。数据元素包含的指针或者指向下一个队列元素,或者为空(此时该元素为队尾元素)上述关系就是队列包中的不变量。
即使不变量有时是不明显的,也很难遇到一个完全没有不变量的程序。当程序遇到被破坏的不变量时,系统可能会返回错误结果甚至立即失败。例如,当程序试图解除对指向无效数据元素的队列头指针的引用时。
2、临界区(critical section)
多线程程序中多个线程共享数据的代码段。由于大部分程序员习惯于思考程序功能而非程序数据,所以你会发现认识临界区比认识数据不变量更容易。不过,临界区总能够对应到一个数据不变量,反之亦然。例如,你从队列中删除数据时,你可以将删除数据的代码视为临界区,也可以将队列状态视为不变量。采取何种考虑方式将决定你最先的想法。
不变量可能会被破坏,而且会经常被独立的代码段破坏。其中的窍门是要确保在“不可预见”的线程访问被破坏的不变量之前将其修复,这也是异步程序中同步机制的大部分工作。同步机制使你的程序免于访问被破坏的不变量。如果一定要(临时的)破坏某个不变量,你需要锁住一个互斥量;当其他线程需要访问该不变量时,它也要试图锁住同一个互斥量。此时,线程就会一直等待,直到你将互斥量解锁并恢复不变量的值后才能访问不变量。
3、谓词(Predicate)
谓词是描述代码所需不变量的状态的语句。在英语中,谓词可以是如“队列为空”、“资
源可用”之类的陈述。谓词可以是一个布尔变量,也可以是测试指针是否为空的测试结果,还可以是更复杂的表达式(如判断计数器是否大于其下限)。谓词甚至可以是某些函数的返回值,如调用select或poll来判断输入文件是否可用。