我有一个音频播放类的竞争条件,每次我开始播放时我将 keepPlaying
设置为 true,而 false 当我停下来。
问题发生在我开始后立即停止(),并且 keepPlaying
标志设置为 false,然后重置为 true再次。
我可以延迟 stop(),但我认为这不是一个很好的解决方案。我是否应该使用条件变量让 stop() 等待直到 keepPlaying
为 true?
您通常会如何解决这个问题?
#include <iostream>
#include <thread>
using namespace std;
class AudioPlayer
{
bool keepRunning;
thread thread_play;
public:
AudioPlayer(){ keepRunning = false; }
~AudioPlayer(){ stop(); }
void play()
{
stop();
// keepRunning = true; // A: this works OK
thread_play = thread(&AudioPlayer::_play, this);
}
void stop()
{
keepRunning = false;
if (thread_play.joinable()) thread_play.join();
}
void _play()
{
cout << "Playing: started\n";
keepRunning = true; // B: this causes problem
while(keepRunning)
{
this_thread::sleep_for(chrono::milliseconds(100));
}
cout << "Playing: stopped\n";
}
};
int main()
{
AudioPlayer ap;
ap.play();
ap.play();
ap.play();
return 0;
}
输出:
$ ./test
Playing: started
(pause indefinitely...)
最佳答案
这是我的建议,结合了下面的许多评论:
1) 将 keepRunning 标志与互斥锁进行简要同步,以便在前一个线程仍在更改状态时无法修改它。
2) 将标志更改为 atomic_bool,因为在不使用互斥锁时它也会被修改。
class AudioPlayer
{
thread thread_play;
public:
AudioPlayer(){ }
~AudioPlayer()
{
keepRunning = false;
thread_play.join();
}
void play()
{
unique_lock<mutex> l(_mutex);
keepRunning = false;
if ( thread_play.joinable() )
thread_play.join();
keepRunning = true;
thread_play = thread(&AudioPlayer::_play, this);
}
void stop()
{
unique_lock<mutex> l(_mutex);
keepRunning = false;
}
private:
void _play()
{
cout << "Playing: started\n";
while ( keepRunning == true )
{
this_thread::sleep_for(chrono::milliseconds(10));
}
cout << "Playing: stopped\n";
}
atomic_bool keepRunning { false };
std::mutex _mutex;
};
int main()
{
AudioPlayer ap;
ap.play();
ap.play();
ap.play();
this_thread::sleep_for(chrono::milliseconds(100));
ap.stop();
return 0;
}
关于c++ - 竞争条件的棘手情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43930221/