下面这段伪代码展示了一个典型的读写场景:
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 ()
和unlock ()
来保护它们?
对您的代码了解不多,但我假设,document
和length
都不是原子。这里需要区分写访问和读访问(假设读访问是const)。写入将改变文档和长度,必须防止其他访问。必须保护读操作不受write调用的影响,但由于读操作既不改变文档也不改变长度,因此允许在多个线程中同时进行。
我冒昧地使用lock_write()
和lock_read()
。使用full 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()
将进入一个繁忙的等待状态,这是不太好的。这可以通过使用条件变量来解决。