程序中哪里有问题,我如何使用 lock() 和 unlock() 解决这些问题?

问题描述

以下伪代码展示了一个典型的读写器场景:

    for (int i = 0; i < N; ++i)
        cout << B[i] << endl;

    delete[] B; //release memory after use
    return 0;

我的问题是: 这个程序哪里会出现并发执行问题? 以及如何仅使用伪代码函数 string document; string::size_type length = 0; write() { while (true) { string text = readFromKeyboard(); document.append(text); length = length + text.length(); } } read() { static string::size_type pos = 0; while (true) { if (pos < length) { process(document.substr(pos,length - pos)); pos = length - 1; } } } main() { unsigned int k = 20; while (k--) Thread consumer(read).start; Thread producer(write).start; wait(); } lock () 来保护它们?

解决方法

对您的代码知之甚少,但我假设 documentlength 都不是原子的。您在这里需要的是写访问和读访问之间的区别(假设读访问是常量)。写入会改变文档和长度,必须防止其他访问。必须通过 write 调用来保护读取不受更改,但由于读取既不改变文档也不改变长度,因此允许一次在多个线程中完成。

我冒昧使用 lock_write()lock_read()。使用完整的 lock() 调用执行此操作会使大多数 read 线程无用。另外,我冒昧地修复了您在 pos = length - 1 函数中的这个 read() 问题。

write() 将变成:

write()
{
    while (true) {
        string text = readFromKeyboard();
        lock_write();
        document.append(text);
        length = length + text.length();
        unlock();
    }
}

read() 将变成:

read()
{
    static string::size_type pos = 0;
    while (true) {
        lock_read();
        if (pos < length) {
            process(document.substr(pos,length - pos));
            pos = length;
        }
        unlock();
    }
}

此外,read() 将进入繁忙的等待状态,这并不好。这可以通过使用条件变量来修复。