c++ - 对boost::: Model进行建模,可以使用信号灯而不是互斥锁(以前的标题:从其他线程解锁互斥锁)

标签 c++ mutex boost-thread

我正在使用C++ boost::thread库,就我而言,这意味着我正在使用pthreads。正式地,互斥锁必须从锁定该线程的同一线程中解锁,我希望能够锁定一个线程然后在另一个线程中解锁的效果。有很多方法可以完成此任务。一种可能性是编写一个允许这种行为的新互斥体类。

例如:

class inter_thread_mutex{
  bool locked;
  boost::mutex mx;
  boost::condition_variable cv;
public:
  void lock(){
    boost::unique_lock<boost::mutex> lck(mx);
    while(locked) cv.wait(lck);
    locked=true;
  }

  void unlock(){
    {
      boost::lock_guard<boost::mutex> lck(mx);
      if(!locked) error();
      locked=false;
    }
    cv.notify_one();
  }
// bool try_lock(); void error(); etc.
}

我应该指出,上面的代码不能保证FIFO访问,因为如果一个线程调用lock()而另一个线程调用unlock(),则第一个线程可能会在其他正在等待的线程之前获取锁。 (来想一想,boost::thread文档似乎并没有为互斥量或条件变量做出任何明确的调度保证)。但是,让我们暂时忽略它(以及所有其他错误)。

我的问题是,如果我决定走这条路,我能否将这种互斥锁用作增强型可锁定概念的模型。例如,如果我使用 boost::unique_lock< inter_thread_mutex > 进行RAII风格的访问,然后将此锁传递给boost::condition_variable_any.wait(),那么会出错吗?

一方面,我不明白为什么不这样做。另一方面,“我不明白为什么不这样做”通常是确定某项内容是否可行的非常糟糕的方法。

我问的原因是,如果事实证明我必须为RAII锁和条件变量以及其他内容编写包装器类,那么我宁愿找到其他方法来实现相同的效果。

编辑:
我想要的行为基本上如下。我有一个对象,只要修改它就需要将其锁定。我想从一个线程中锁定对象,并对其进行一些工作。然后,当我告诉另一个工作线程完成工作时,我想保持对象锁定。因此,在工作线程完成时,第一个线程可以继续执行其他操作。工作线程完成后,它将解锁互斥锁。

而且我希望这种过渡看起来很平稳,这样当线程1开始工作而线程2完成工作时,没人能在两者之间获得互斥锁。

诸如inter_thread_mutex之类的东西似乎可以工作,并且还允许该程序与它进行交互,就好像它是普通的互斥锁一样。因此,这似乎是一个干净的解决方案。如果有更好的解决方案,我也很高兴听到。

再次编辑:
我之所以需要锁,是因为有多个主线程,并且那里的锁可以防止它们以无效方式并发访问共享对象。
因此,代码已经在主线程级别使用了循环级别的无锁操作序列。另外,在原始实现中,没有工作线程,并且互斥锁是普通的洁食互斥锁。

inter_thread_thingy是一项优化,主要是为了缩短响应时间。在许多情况下,足以保证操作A的“第一部分”出现在操作B的“第一部分”之前。举个愚蠢的例子,我对对象1进行打孔,然后给它黑眼睛。然后,我告诉对象1更改其内部结构以反射(reflect)所有组织损伤。我不想在继续对物体2进行打孔之前等待组织损伤。但是,我确实希望组织损伤是在同一操作中发生的;因此,我希望对组织进行损伤。例如,在此期间,我不希望任何其他线程重新配置该对象,从而使组织损坏成为无效操作。 (是的,这个示例在许多方面都不完美,不,我不是在玩游戏)

因此,我们对模型进行了更改,在该模型中,对象的所有权可以传递给工作线程以完成操作,并且实际上效果很好。每个主线程能够完成更多的操作,因为它不需要等待它们全部完成。而且,由于主线程级的事件排序仍基于循环,因此编写高级主线程操作很容易,因为它们可以基于操作已完成的假设(更确切地说,关键的“当相应的函数调用返回时,排序逻辑所依赖的“第一部分”就完成了。

最后,我认为最好将带有RAII的inter_thread互斥体/信号量东西与boost锁一起使用,以封装使整个东西正常工作所需的必要同步。

最佳答案

man pthread_unlock(在OS X上,类似于Linux上的措辞)具有答案:

名称
pthread_mutex_unlock-解锁互斥锁

概要
#include

整型
pthread_mutex_unlock(pthread_mutex_t * mutex);

描述
如果当前线程持有互斥锁,则
pthread_mutex_unlock()函数可解锁互斥锁。

使用互斥锁调用pthread_mutex_unlock()
调用线程不成立将导致
未定义的行为。

...

我的反问是-您试图以此解决哪种同步问题?很可能有一个更简单的解决方案。
pthreadsboost::thread(在其顶部构建)都不能保证竞争线程获取竞争互斥体的任何顺序。

关于c++ - 对boost::: Model进行建模,可以使用信号灯而不是互斥锁(以前的标题:从其他线程解锁互斥锁),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2754884/

相关文章:

c - 互斥量动态分配

c++ - 如何检查boost线程正在运行并杀死它

c++ - 如何在 boost tcp/udp 服务器中处理 control-c

c++ - 使用 Boost::Asio 停止线程服务器循环

c++ - 当 return 语句、逗号运算符、花括号初始化列表和 std::unique_ptr 组合在一起时

C++构造函数问题

c++ - STL 迭代器的语法是如何实现的?

c++ - 实例化 std::mutex 时出现编译器错误

pthreads - 正确使用 MPI_THREAD_SERIALIZED 和 pthreads

c++ - 从 vector<string> 到非标量类型 string 的转换