如何检查线程是否被锁定

时间:2018-10-30 05:13:29

标签: c++ multithreading boost synchronization

我希望检查线程是否被boost.thread库锁定。 我编写了以下代码进行测试。

worker.h

#pragma once

#include <boost/thread.hpp>

class Worker
{
  private:
    boost::thread *_thread;
    boost::thread *_checker_thread;
    boost::condition_variable _cond;
    boost::mutex _mutex;
    bool _run;
    int _id;

  public:
    Worker(int id);
    ~Worker();

    void initialize();
    void start();
    void join();

    static unsigned process(void *param);
    static unsigned check_running(void *param);
};

worker.cpp:

#include "worker.h"
#include <iostream>
#include <boost/chrono.hpp>

Worker::Worker(int id) : _thread(nullptr)
{
  _id = id;
}

Worker::~Worker()
{
  std::cout << "Invoked destructor()" << std::endl;

  if (_thread) {
    delete _thread;
    _thread = nullptr;
  }
}

void Worker::initialize()
{
  std::cout << "Invoked initialize()" << std::endl;

  boost::thread::attributes attrs;
  _run = true;

  try {
    _thread = new boost::thread(attrs, boost::bind(Worker::process, this));
    _checker_thread = new boost::thread(attrs, boost::bind(Worker::check_running, this));
  } catch(...) {
    std::cerr << "Begin thread error" << std::endl;

    if (_thread) {
      delete _thread;
      _thread = nullptr;
    }

    if (_checker_thread) {
      delete _checker_thread;
      _checker_thread = nullptr;
    }
  }
}

void Worker::start()
{
  std::cout << "Invoked start()" << std::endl;
  _cond.notify_one();
}

void Worker::join()
{
  std::cout << "Invoked join()" << std::endl;

  if (_thread) {
    _thread->join();
  }
}

unsigned Worker::process(void *param)
{
  std::cout << "Invoked process()" << std::endl;

  Worker *worker = (Worker*)param;
  boost::unique_lock<boost::mutex> lock(worker->_mutex);

  while (worker->_run) {
    worker->_cond.wait(lock);
    std::cout << "Start process" << std::endl;

    for (int i = 0; i < 20; i++) {
      boost::this_thread::sleep_for(boost::chrono::milliseconds{1});
      std::cout << i << std::endl;
    }

    worker->_run = false;
  }

  return 0;
}

unsigned Worker::check_running(void *param)
{
  Worker *worker = (Worker*)param;

  std::cout << "Start check running" << std::endl;

  while (worker->_run) {
    if (worker->_mutex.try_lock()) {
      std::cout << '-';
      worker->_mutex.unlock();
    } else {
      std::cout << '+';
    }

    boost::this_thread::sleep_for(boost::chrono::milliseconds{1});
  }

  return 0;
}

main.cpp:

#include "worker.h"
#include <iostream>

int main()
{
  Worker worker(99);

  worker.initialize();

  for (int i = 0; i < 26; i++)
  {
    if (i == 5)
    {
      worker.start();
    }

    boost::this_thread::sleep_for(boost::chrono::milliseconds{1});
    std::cout << static_cast<char>(i + 'a') << std::endl;
  }

  worker.join();

  return 0;
}

此代码具有3个线程:

  1. 在main()中从a到z打印字母。
  2. 在Worker :: process()中打印从0到19的数字。在打印“ e”后启动。
  3. 检查打印号码线程是否在Worker :: check_running()中被锁定。如果已锁定,则打印“ +”,否则显示“-”。

在Worker :: check_running()中,我使用了mutex.try_lock()检查线程是否被锁定。但是,在这种情况下,必须调用Mutex.unlock()。

如何使该代码成为RAII风格?我的意思是我想使用另一个锁模板,例如boost :: unique_lock <>,以避免丢失互斥锁(mutex.unlock())。


@Miles Budnek,

谢谢您的回答。

我应用了您的答案,但结果却有所不同。

我的代码显示结果如下:

Invoked initialize()
Invoked process()Start check running

-a
-b
-c
-d
-e
Invoked start()
Start process
+f
+0
g
+1
h
+2
i

...

17
x
+18
y
+19
z
Invoked join()
Invoked destructor()

您的代码如下:

Invoked initialize()
Invoked process()
Start check running
-a
-b
-c
--d
-e
Invoked start()
-f
-g
-h

...

-x
-y
-z
Invoked join()
---------------- ... -----------Start process
++0
+1
+2
+3
+4
5
+6
+7

...

+18
+19
Invoked destructor()

请检查一下吗?

1 个答案:

答案 0 :(得分:0)

您可以将boost::unique_lockboost::try_to_lock参数一起使用:

while (worker->_run) {
  boost::unique_lock<boost::mutex> lock(worker->_mutex, boost::try_to_lock);
  if (lock.owns_lock()) {
    std::cout << '-';
  } else {
    std::cout << '+';
  }

  boost::this_thread::sleep_for(boost::chrono::milliseconds{1});
}