- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写一个 Audio
类,它包含一个 std::thread
用于异步填充一些缓冲区。假设我们调用主线程 A 和后台(类成员)线程 B。我正在使用 std::mutex
在声音未播放时阻止线程 B,那样它就不会不需要时在后台运行,不会占用过多的 CPU 资源。默认情况下,线程 A 锁定互斥量,因此线程 B 被阻塞,然后在播放声音时线程 A 解锁互斥量,线程 B 循环运行(通过锁定然后立即解锁)。
当线程 B 发现它已到达文件末尾时,问题就出现了。它可以停止播放和清理缓冲区等,但它不能停止自己的循环,因为线程 B 无法锁定线程 A 的互斥量。
相关代码大纲如下:
class Audio {
private:
// ...
std::thread Thread;
std::mutex PauseMutex; // mutex that blocks Thread, locked in constructor
void ThreadFunc(); // assigned to Thread in constructor
public:
// ...
void Play();
void Stop();
}
_
void Audio::ThreadFunc() {
// ... (include initial check of mutex here)
while (!this->EndThread) { // Thread-safe flag, only set when Audio is destructed
// ... Check and refill buffers as necessary, etc ...
if (EOF)
Stop();
// Attempt a lock, blocks thread if sound/music is not playing
this->PauseMutex.lock();
this->PauseMutex.unlock();
}
}
void Audio::Play() {
// ...
PauseMutex.unlock(); // unlock mutex so loop in ThreadFunc can start
}
void Audio::Stop() {
// ...
PauseMutex.lock(); // locks mutex to stop loop in ThreadFunc
// ^^ This is the issue here
}
在上面的设置中,当后台线程发现它到达 EOF 时,它会调用类的 Stop()
函数,该函数应该锁定互斥锁以停止后台线程。这是行不通的,因为互斥量必须由主线程锁定,而不是后台线程(在这个例子中,它在 ThreadFunc
中崩溃,因为后台线程在之后尝试在其主循环中锁定已经锁定在 Stop()
中。
在这一点上,我唯一能想到的就是以某种方式让后台线程锁定互斥量就好像它是主线程一样,让主线程拥有互斥量...如果那可能的话?有没有办法让线程将互斥体的所有权转移给另一个线程?或者这是我创建的设置中的设计缺陷? (如果是后者,是否有任何合理的解决方法?)到目前为止,类里面的其他所有内容都按设计工作。
最佳答案
我什至不会假装理解你的代码是如何尝试做它正在做的事情的。然而,有一件事是显而易见的。您正在尝试使用互斥锁来传达某些谓词状态更改,这是在该高速公路上行驶的错误车辆。
谓词状态变化是通过耦合三件事来处理的:
目标
以下示例的目标是演示在控制跨多个线程的程序流时如何协同使用互斥体、条件变量和谓词数据。它显示了使用 wait
和 wait_for
条件变量功能的示例,以及一种将成员函数作为线程过程运行的方法。
下面是一个简单的 Player
类,它在四种可能的状态之间切换:
谓词数据相当明显。 状态 成员。它必须受到保护,这意味着除非在互斥锁的保护下,否则不能更改也不能检查。我在其中添加了一个 counter
,它会在保持 Playing 状态一段时间的过程中简单地递增。更具体地说:
计数器
每 200 毫秒递增一次,然后将一些数据转储到控制台。 计数器
不会改变,但会保留播放时的最后一个值。这意味着当恢复时,它将从中断的地方继续。计数器
重置为零,并在控制台输出中注入(inject)换行符。这意味着切换回播放将重新开始计数器序列。counter
没有影响,它将与其他所有内容一起消失。代码
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <unistd.h>
using namespace std::chrono_literals;
struct Player
{
private:
std::mutex mtx;
std::condition_variable cv;
std::thread thr;
enum State
{
Stopped,
Paused,
Playing,
Quit
};
State state;
int counter;
void signal_state(State st)
{
std::unique_lock<std::mutex> lock(mtx);
if (st != state)
{
state = st;
cv.notify_one();
}
}
// main player monitor
void monitor()
{
std::unique_lock<std::mutex> lock(mtx);
bool bQuit = false;
while (!bQuit)
{
switch (state)
{
case Playing:
std::cout << ++counter << '.';
cv.wait_for(lock, 200ms, [this](){ return state != Playing; });
break;
case Stopped:
cv.wait(lock, [this]() { return state != Stopped; });
std::cout << '\n';
counter = 0;
break;
case Paused:
cv.wait(lock, [this]() { return state != Paused; });
break;
case Quit:
bQuit = true;
break;
}
}
}
public:
Player()
: state(Stopped)
, counter(0)
{
thr = std::thread(std::bind(&Player::monitor, this));
}
~Player()
{
quit();
thr.join();
}
void stop() { signal_state(Stopped); }
void play() { signal_state(Playing); }
void pause() { signal_state(Paused); }
void quit() { signal_state(Quit); }
};
int main()
{
Player player;
player.play();
sleep(3);
player.pause();
sleep(3);
player.play();
sleep(3);
player.stop();
sleep(3);
player.play();
sleep(3);
}
输出
我无法真正证明这一点。您必须运行它并查看它是如何工作的,我邀请您像我上面那样玩弄 main()
中的状态。但是请注意,一旦 quit
被调用,则不会监视任何其他状态。设置退出状态将关闭监视器线程。对于它的值(value),上面的运行应该看起来像这样:
1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.
1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.
第一组数字被分成两组(1..15,然后是 16..30),作为播放的结果,然后暂停,然后再次播放。然后发出停止信号,然后再播放约 3 秒。之后,对象自毁,并在这样做时设置 Quit 状态,并等待监视器终止。
总结
希望你能从中有所收获。如果您发现自己试图通过手动锁定和释放互斥锁来管理谓词状态,那么您需要一个条件变量设计模式来帮助检测这些变化。
希望你能从中有所收获。
关于C++ 像从另一个线程一样锁定互斥量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51668477/
我只是有一个关于 Java 并发编程的简单问题。例如,我有一个 NxN 矩阵,矩阵的每一行都有一个对应的线程,如果每一行中的线程之间没有交互,如果多个线程同时访问和修改矩阵的单独行是否安全(或正确)?
jwplayer("myElement_0").onPlay(function(){ pausePlayers(1); alert('0 has started'); }); jwplayer("my
我在想。当我使用一个std::mutex _lock 并想依赖守卫来释放它时,我可以这样使用吗? class MyClass{ private: mutable std::mutex _loc
这种互斥模式是否像我认为的那样安全?如果是这样,你怎么调用它? lock (_lock) { if (_flag) return; else _flag = true; } try {
我有一个静态库 来访问数据库。它有一个函数 readMaximum()。 readMaximum() 从数据库中读取最大值。此函数是线程安全的(使用互斥量)。 但问题是: 有两个进程A.exe和B.e
我正在为互斥锁的逻辑而苦苦挣扎;我在这里检查 key 是否被拿走,如果没有,我们拿走它,完成后释放它;但是你能帮我看看我怎样才能有一个循环来检查 key 直到它可用吗? rdb.setnx(lockk
我正在使用 clp(fd) 编写 Prolog 程序并且我很难实现我想要的约束之一。 输出是一个整数列表(长度取决于程序另一部分的输入),其中有某些相互排斥的预定义数字对,每对中的一个数字必须在输出中
我正在尝试使用 mesos/marathon 实现一个 lizardfs 集群。为此,我创建了一些 docker 镜像。 我需要获取某种类型的 docker 容器(lizardfs-master),而
假设我有一个包含以下列的 MySQL 表: |variables|1. | 'a' |2. | 'a b' |3. | 'a b c' |4. | ... | How can
我在一个表单上有 7 个单选按钮 其中3个属于一个组,4个属于另一个组 我希望 RadioButtons 在组内互斥。 这可以通过将它们放在两个 GroupBox 中来实现, 有没有什么办法可以不把它
我正在尝试使文本输入和复选框相互排斥。 默认情况下,文本框应包含“0”,复选框应为 false。如果用户选中该复选框,则该文本框应被清空。如果用户在文本框中输入值,则应取消选中该复选框。任何时候都不应
我已经在代码的注释中写下了我的问题。 我正在尝试使用 pthreads 使我的代码并行。首先,我想通过多个线程并行地在内存中写入大量数据。写入数据后,我想通过相同的线程执行此数据。执行数据后,我想读取
这个问题在这里已经有了答案: 关闭 13 年前。 Possible Duplicate: Monitor vs Mutex in c# 你好, 在这个网站上,我发现来自不同人的不同答案令人困惑。仍然
我需要调用一个返回唯一 id 的函数, int getid() { static id=0; id++; return id; } 多个线程需要调用这个函数,我的问题是我不确定我需要在哪里锁定互斥量,
请引用来自 WWDC 的视频 https://developer.apple.com/videos/play/wwdc2015/226/演讲者展示了我们可以在两个相同类型的 NSopeation 实例
概述: 我有一个使用 CoreData 的 iOS 应用程序> 有一个名为Animal的实体 它有一组记录Lion、Tiger和Elephant 我想将只有一个记录标记为收藏。 具有相同方法的相似实体
这个问题在这里已经有了答案: 关闭 12 年前。 Possible Duplicate: DLL thread safety 你好 我正在 MS VS C++ express 中编写一个 DLL 文
我的应用程序被迫使用第 3 方模块,如果在同一台机器上同时启动两个实例,该模块将使 Windows 蓝屏。为了解决这个问题,我的 C# 应用程序有一个互斥量: static Mutex mutex =
我是 Go 的新手,我想实现一个自定义的互斥机制,每个应用程序用户一次可以执行一个 goroutine。为简化起见,将 U1 和 U2 视为应用程序用户以及 F1(userId)、F2(userId)
我需要将单选和多选的功能组合到一个控件中。具体来说,我有多种选择。第一个与其他的互斥。所以,如果我选择第一个,就需要取消选中所有其他的。如果选择了其中一个,则必须取消选中第一个(如果已选择)。其他选项
我是一名优秀的程序员,十分优秀!