Sun Studio 12 Update 1:C++ 用户指南

11.4.5 对象锁定

最简单的共享对象和多线程问题处理策略是通过确保 iostream 对象是线程局部对象来避免问题。例如,

不过在许多情况下(例如缺省共享标准流对象),使对象专用于某线程是不可能的,这就需要其他的策略了。

要独立对 iostream 类对象执行一序列操作,必须使用某种形式的锁定。锁定会增加一些开销,即使是在单线程应用程序中也是如此。是增加锁定还是使 iostream 对象成为线程的专用对象取决于为应用程序选择的线程模型: 线程是独立的还是协同操作的?

11.4.5.1 stream_locker

iostream 库提供了 stream_locker 类,用于锁定针对 iostream 对象的一系列操作。因此可以将动态启用或禁用 iostream 对象的锁定所造成的性能开销降到最低。

可以使用 stream_locker 类的对象使针对流对象的一序列操作独立化。例如,下例中所示代码尝试查找文件中的某一位置,并读取下一个数据块。


示例 11–10 使用锁定操作的示例


#include <fstream.h>
#include <rlocks.h>

void lock_example (fstream& fs)
{
    const int len = 128;
    char buf[len];
    int offset = 48;
    stream_locker s_lock(fs, stream_locker::lock_now);
    .....// open file
    fs.seekg(offset, ios::beg);
    fs.read(buf, len);
}

在此示例中,stream_locker 对象的构造函数定义了每次只能执行一个线程的互斥区域的开始位置。从函数返回后调用的析构函数定义了互斥区域的结束位置。stream_locker 对象确保了在文件中查找特定偏移和从文件中读取能够同时独立执行,并且在原来的 ThreadA 读取文件之前,ThreadB 不能更改文件偏移。

另一种使用 stream_locker 对象的方法是显式定义互斥区域。在以下示例中,为了使 I/O 操作和后续错误检查独立化,使用了 vbstream_locker 对象的成员函数 lockunlock 调用。


示例 11–11 令 I/O 操作和错误检查独立化


{
    ...
    stream_locker file_lck(openfile_stream,
                             stream_locker::lock_defer);
    ....
    file_lck.lock();  // lock openfile_stream
    openfile_stream << "Value: " << int_value << "\n";
    if(!openfile_stream) {
            file_error("Output of value failed\n");
            return;
    }
    file_lck.unlock(); // unlock openfile_stream
}

有关更多信息,请参见 stream_locker(3CC4) 手册页。