关于多线程的问题

wanren13 2015-09-28 01:44:32
synchronized_list.h:

#ifndef SYNCHRONIZED_LIST_H
#define SYNCHRONIZED_LIST_H

#include <iostream>
#include <vector>
#include <mutex>


using namespace std;

template <class T>
class SyncList {
public:
SyncList() :low_mark(0), high_mark(1), hasShutDown(false) {};
SyncList(size_t l, size_t h) :
low_mark(l), high_mark(h), hasShutDown(false) {
if (low_mark < 0) low_mark = 0;
if (high_mark <= 0) high_mark = 1;
};
SyncList(const SyncList&);
void push_back(const T&);
void pop_back(T&);
void push_front(const T&);
void pop_front(T&);
bool empty() const;
void shut_down();
void reset();
private:
bool hasShutDown;
size_t low_mark;
size_t high_mark;
mutable mutex mtx;
condition_variable cond;
vector<T> vec;
};

template <class T>
SyncList<T>::SyncList(const SyncList<T>& other) {
lock(mtx, other.mtx);
lock_guard<mutex> lck1(mtx, adopt_lock);
lock_guard<mutex> lck2(other.mtx, adopt_lock);
low_mark = other.low_mark;
high_mark = other.high_mark;
vec = other.vec;
}

template <class T>
void SyncList<T>::push_back(const T& value)
{
unique_lock<mutex> lck(mtx);

cond.wait(lck, [this] {
return vec.size() <= high_mark;
});
cout << "Push back " << value << endl;
vec.push_back(value);
cond.notify_one();
}

template <class T>
void SyncList<T>::pop_back(T& value)
{
if (!hasShutDown) {
unique_lock<mutex> lck(mtx);
cond.wait(lck, [this] {
return vec.size() >= low_mark;
});
// lck.unlock();
value = vec.back();
vec.pop_back();
cout << "Pop back " << value << " Size of list is: " << vec.size() << " is shut_down: " << (hasShutDown?"Yes":"No") << endl;
cond.notify_one();
}
}

template <class T>
void SyncList<T>::push_front(const T& value)
{
unique_lock<mutex> lck(mtx);
cond.wait(lck, [this] {
return vec.size() <= high_mark;
});
cout << "Push front " << value << endl;
vec.insert(vec.begin(), value);
cond.notify_one();
}

template <class T>
void SyncList<T>::pop_front(T& value)
{
unique_lock<mutex> lck(mtx);
cond.wait(lck, [this] {
return vec.size() >= low_mark;
});
// lck.unlock();
value = vec.front();
cout << "Pop front " << value << endl;
vec.erase(vec.begin());
cond.notify_one();
}

template <class T>
bool SyncList<T>::empty() const {
lock_guard<mutex> lck(mtx);
return vec.empty();
}

template <class T>
void SyncList<T>::shut_down() {
//{
lock_guard<mutex> lck(mtx);
hasShutDown = true;
cond.notify_all();
//}
// hasShutDown = false;
}

template <class T>
void SyncList<T>::reset() {
lock_guard<mutex> lck(mtx);
hasShutDown = false;
}

#endif

active_object.h:

#ifndef ACTIVE_OBJECT_H
#define ACTIVE_OBJECT_H

#include "synchronized_list.h"

using namespace std;

template <class T>
class ActiveObj {
public:
ActiveObj() :list(SyncList<T>(1, 500)), isActive(false) {};
void enque(const T&);
void active();
void deactive();
private:
SyncList<T> list;
void run_service();
bool isActive;
};

template <class T>
void ActiveObj<T>::enque(const T& value) {
list.push_front(value);
}

template <class T>
void ActiveObj<T>::active() {
if (!isActive) {
isActive = true;
list.reset();
thread(&ActiveObj<T>::run_service, this).detach();
// thread(&ActiveObj<T>::run_service, this).join();
// cout << "Thread joined" << endl;
}
}

template <class T>
void ActiveObj<T>::deactive() {
isActive = false;
list.shut_down();
}

template <class T>
void ActiveObj<T>::run_service() {
T value;
while (isActive) {
if (list.empty()) {
this_thread::yield();
}
else {
cout << "I'm running" << endl;
list.pop_back(value);
}
}
}

#endif

active_object.cpp:


#include <iostream>
#include <mutex>
#include <stdlib.h>
#include <thread>
#include <time.h>
#include <random>
#include <chrono>
#include "active_object.h"


int numbers[500];

template <class T>
void pushFifty(ActiveObj<T>& obj) {
for (int i = 0; i < 500; i++) {
obj.enque(numbers[i]);
}
}


int main(int argc, char* argv[])
{
ActiveObj<int> obj;
srand(time(NULL));


for (int i = 0; i < 500; i++) {
numbers[i] = rand() % 500 + 1;
cout << numbers[i] << " ";
}

cout << endl;

//*
cout << "Starting pushing" << endl;
pushFifty(obj);

cout << "Active now" << endl;
obj.active();

cout << "Sleep 3 seconds" << endl;
this_thread::sleep_for(chrono::seconds(3));

cout << "Pushing again" << endl;
pushFifty(obj);

cout << "Starting Deactiving" << endl;
obj.deactive();

cout << "Active again" << endl;
obj.active();

cout << endl;
//*/

return EXIT_SUCCESS;
}

运行结果:

麻烦各位大侠帮忙看一下代码,帮我找一下错误所在。小弟我弄了两天了,没有找到错误,快要崩溃了。
ActiveObj类有一个active函数,作用是用来启动run_service函数来pop完所有存在SyncList的东西。
我的问题是,为什么当我再次执行active函数的时候(active_obj.cpp第51行)的时候,程序只执行了一次pop就结束了???(结果如贴图所示)

...全文
158 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
jiqiang01234 2015-09-29
  • 打赏
  • 举报
回复
楼主似乎是要做一个带有上下限位的多线程的任务队列。不过为何底层结构要用std::vector<char>来做,明显vector是不合使用push_front()的操作的。 任务线程如果创建了,一般就不会退出了,知道进程结束。
jiht594 2015-09-29
  • 打赏
  • 举报
回复
引用 5 楼 wanren13 的回复:
[quote=引用 4 楼 lianshaohua 的回复:] 试一下thread的join函数,让join函数等thread退出
那应该什么时候用detach呢?[/quote] detach之后那些线程还在运行吧, 你把log输出到文件看一下. 猜的
wanren13 2015-09-29
  • 打赏
  • 举报
回复
引用 4 楼 lianshaohua 的回复:
试一下thread的join函数,让join函数等thread退出
那应该什么时候用detach呢?
ztenv 版主 2015-09-28
  • 打赏
  • 举报
回复
试一下thread的join函数,让join函数等thread退出
wanren13 2015-09-28
  • 打赏
  • 举报
回复
引用 1 楼 iyomumx 的回复:
因为程序结束了啊
貌似是这样的。。。在主程序结尾加入了一条sleep语句就好了。。。 但是问题来了,如果一个thread被detach了,我该如何管理这个thread呢?如果用sleep语句的话,我并不知道该sleep多长时间
wanren13 2015-09-28
  • 打赏
  • 举报
回复
引用 1 楼 iyomumx 的回复:
因为程序结束了啊
大侠你好,用来pop的thread被detach出来,主程序结束也会影响到吗?
iyomumx 2015-09-28
  • 打赏
  • 举报
回复
因为程序结束了啊

64,647

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧