【问题标题】:Sleep or semaphore for background thread后台线程的睡眠或信号量
【发布时间】:2015-05-21 12:46:27
【问题描述】:

我有第三方代码,它使用这样的代码创建了很多线程:

while (true) {
    {
        my::Lock lock(&mMutex); // mutex implementation in c++
        if (!reseting) {
            // some code
            break;
        }
    }
    usleep(1000 / 20); // 20 time per second
}

我可以用semaphore 重写这段代码。使用什么,semaphore 或 sleep?据我了解,它们的工作方式相同。 Semaphore 会更快一点,因为当reset 更改时,我们可以立即继续此thread。

或者也许您有其他想法如何更好地做到这一点?


my::Lock的实现:

Lock::Lock(pthread_mutex_t *mutex) {
    _mutex = mutex;
    pthread_mutex_lock(_mutex);
}

Lock::~Lock() {
    pthread_mutex_unlock(_mutex);
}

【问题讨论】:

  • my::Lock 在释放时解锁互斥锁。此对象在usleep 之前发布。这个后台进程有时会使用睡眠代码进行大量计算,所以我相信当调用睡眠时处理器仍然可以工作,但在另一个线程上。
  • 啊,释放后重新解锁,有道理。这就解释了神秘的{ 范围。不过,我不确定其他线程如何使用相同的锁(因为我假设该锁的目的是同步reseting)。即使这不是问题,我也不喜欢这种隐式解锁模式。但所有这些都没有实际意义,因为更广泛的问题是轮询,一般来说,(忽略使用互斥锁的事实!)每秒 20 次,效率低下。使用委托或完成块或通知或其他一些主动过程会更好。尽可能避免旋转/等待。

标签: objective-c multithreading semaphore objective-c++ thread-sleep


【解决方案1】:

您是正确的,轮询是一种低效的方法。这种互斥锁实现只会让情况变得更糟。

你问信号量是否是更好的模式:它可能是,但我怀疑你可以做得更好。具体来说,我想到了三种异步模式:

  • “完成处理程序”模式,其中 API 调用采用块参数,该参数是异步任务完成时将调用的代码块。当您需要一个简单的接口来通知调用者异步任务完成时,这是理想的选择。

  • “delegate-protocol”模式,其中 API 将有一个 delegate 属性来指定通知谁,以及一个定义 delegate 可能或必须实现的方法的协议。这是一种有用的模式,用于通信更新的接口更复杂(例如,不仅是在任务完成时,还可能是各种进度更新)。

  • “通知”模式(使用NSNotificationCenter 通知其他对象状态更改)。如果有可能不止一个对象想要获知任务的完成,这将非常有用。

坦率地说,选择可能取决于此第三方库的详细信息。根据提供的信息很难评估。

【讨论】:

  • 这段代码针对不同的架构编写。我怎么知道使用睡眠是不好的做法。例如,如果我用“完成处理程序”模式重写所有这些代码,我会获得更多的应用程序性能吗?现在创建 4-5 个线程进行大量计算。当一个线程处于休眠状态时,处理器在另一个线程中进行计算。另外,如果我重写一些模式,代码的可读性会降低。
  • 是的,轮询和usleep 不是很好,但是使用信号量通常也好不了多少,恕我直言。这取决于。但是,从实际的角度来看,更重要的代码重构很可能不值得付出努力,因为收益可能不大。事实上,这都是过早优化的味道。
猜你喜欢
  • 2020-07-26
  • 1970-01-01
  • 2018-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-08
相关资源
最近更新 更多