简体   繁体   English

如何正确使用互斥锁?

[英]How to use mutex properly?

I have mailBox class with send and receive methods shared between threads, and threads: thread1 send message, threads 2 and 3 receive messages, how I must using mutex for synchronize this?我有邮箱 class,线程之间共享发送和接收方法,线程:线程 1 发送消息,线程 2 和 3 接收消息,我必须如何使用互斥锁进行同步?

Any combinations that I have tried hasn't led to success.我尝试过的任何组合都没有成功。

std::mutex g_lock; //in global
void sendMessage(Message msg) {
    if (g_lock.try_lock()) {
        this_thread::sleep_for(100ms); // DELAY
        messages->push_back(msg);
        g_lock.unlock();
    }
}

The same for Receive method接收方法也一样

full code: https://pastebin.com/7y2RC5br完整代码: https://pastebin.com/7y2RC5br

Also this code can't be debugged because delays change the logic of the code.此外,无法调试此代码,因为延迟会更改代码的逻辑。

Correct logic of the code: thread2/3 try lock and read msg, get empty then unlock thread1 try lock and send msg then unlock thread2/3 try lock and read msg, get msg and write to file then unlock代码的正确逻辑:thread2/3 尝试锁定并读取 msg,获取空然后解锁 thread1 尝试锁定并发送 msg 然后解锁 thread2/3 尝试锁定并读取 msg,获取 msg 并写入文件然后解锁

When I have tried mutex's try_lock from threads 2/3, I had been getting constantly blocked thread and thread 1 was had been working after ALL threads 2/3.当我从线程 2/3 尝试互斥锁的 try_lock 时,我一直在不断地阻塞线程,并且线程 1 在所有线程 2/3 之后一直在工作。

Box up low level mutexes into building block types.将低级互斥锁组合成构建块类型。

Lock based thread safety is ridiculously easy to get wrong.基于锁的线程安全非常容易出错。 Not only is it fragile, it doesn't compose;它不仅脆弱,而且不合成; three routines that are pairwise thread safe can be when combined unsafe.三个成对线程安全的例程在组合时可能是不安全的。

Thread safety is a relational property, not an absolute one.线程安全是一种关系属性,而不是绝对属性。

There are various known patterns that have been mathematically proven to work.有多种已知模式已在数学上证明有效。 Implemented correctly and you are less doomed.正确实施,你就不会那么失败了。 Toss together something, and your code won't be correct.折腾一些东西,您的代码将不正确。

To design new threading code you will want to get good at proof based computer science.要设计新的线程代码,您需要精通基于证明的计算机科学。 The implementation is easier than designing it correctly.实现比正确设计更容易。

In your case, I would start with a thread safe queue primitive.在您的情况下,我将从线程安全队列原语开始。 You'll need condition variables, mutexes, and a std deque.您将需要条件变量、互斥体和标准双端队列。 Then hook each routine up to one end of a queue, and send messages to the other.然后将每个例程连接到队列的一端,并将消息发送到另一端。 (The reader should only read from a queue and consume each message in order; the writer, only send messages on a queue). (读取器应该只从队列中读取并按顺序消费每条消息;写入器只在队列上发送消息)。

I mean, this is still going to be hard to get right, but at least your primitives aren't nearly raw mutexes.我的意思是,这仍然很难正确,但至少您的原语几乎不是原始互斥锁。

template<class T>
struct threadsafe_queue {
  T pop();
  void push(T);
  std::deque<T> pop_all();

  std::optional<T> try_pop();
  template<class...Ts>
  std::optional<T> wait_for_pop( std::chrono::duration<Ts...> );
private:
  mutable std::mutex m;
  std::condition_variable cv;
  std::deque<T> queue;
  std::unique_lock<std::mutex> lock() const;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM