2015-06-11 16 views
10

Tôi có chuỗi tăng x hoạt động cùng một lúc. Một chuỗi nhà sản xuất điền vào hàng đợi được đồng bộ hóa với các nhiệm vụ tính toán. Chủ đề người tiêu dùng bật ra nhiệm vụ và tính toán chúng.Tắt chủ đề chính xác

Synchronised Queue Hình ảnh Nguồn: https://www.quantnet.com/threads/c-multithreading-in-boost.10028/

Người dùng có thể kết thúc programm trong quá trình này, vì vậy tôi cần phải tắt máy đề của tôi đúng. Cách tiếp cận hiện tại của tôi dường như không hoạt động, vì các ngoại lệ được ném ra. Đó là ý tưởng rằng trên hệ thống tắt tất cả các quá trình nên bị giết và ngừng nhiệm vụ hiện tại của họ không có vấn đề gì họ làm. Bạn có thể vui lòng chỉ cho tôi, làm thế nào bạn sẽ giết chủ đề?

Chủ đề initialisation:

for (int i = 0; i < numberOfThreads; i++) 
    { 
     std::thread* thread = new std::thread(&MyManager::worker, this); 
     mThreads.push_back(thread); 
    } 

Chủ đề Tiêu hủy:

void MyManager::shutdown() 
{ 
    for (int i = 0; i < numberOfThreads; i++) 
    { 
     mThreads.at(i)->join(); 
     delete mThreads.at(i); 
    } 
    mThreads.clear(); 
} 

Worker:

void MyManager::worker() 
{ 
    while (true) 
    { 

     int current = waitingList.pop(); 
     Object * p = objects.at(current); 
     p->calculateMesh(); //this task is internally locked by a mutex 

     try 
     { 
      boost::this_thread::interruption_point(); 
     } 
     catch (const boost::thread_interrupted&) 
     { 
      // Thread interruption request received, break the loop 
      std::cout << "- Thread interrupted. Exiting thread." << std::endl; 
      break; 
     } 
    } 
} 

đồng bộ Queue:

#include <queue> 
#include <thread> 
#include <mutex> 
#include <condition_variable> 

template <typename T> 
class ThreadSafeQueue 
{ 
public: 

    T pop() 
    { 
     std::unique_lock<std::mutex> mlock(mutex_); 
     while (queue_.empty()) 
     { 
      cond_.wait(mlock); 
     } 
     auto item = queue_.front(); 
     queue_.pop(); 

     return item; 
    } 

    void push(const T& item) 
    { 
     std::unique_lock<std::mutex> mlock(mutex_); 
     queue_.push(item); 
     mlock.unlock(); 
     cond_.notify_one(); 
    } 


    int sizeIndicator() 
    { 
     std::unique_lock<std::mutex> mlock(mutex_); 
     return queue_.size(); 
    } 


private: 

    bool isEmpty() { 
     std::unique_lock<std::mutex> mlock(mutex_); 
     return queue_.empty(); 
    } 

    std::queue<T> queue_; 
    std::mutex mutex_; 
    std::condition_variable cond_; 
}; 

Các ném gọi lỗi stack:

... std::_Mtx_lockX(_Mtx_internal_imp_t * * _Mtx) Line 68 C++ 
... std::_Mutex_base::lock() Line 42 C++ 
... std::unique_lock<std::mutex>::unique_lock<std::mutex>(std::mutex & _Mtx) Line 220 C++ 
... ThreadSafeQueue<int>::pop() Line 13 C++ 
... MyManager::worker() Zeile 178 C++ 
+0

Hai điều: isEmpty không bị khóa và kích thước() có thể có một thực hiện đơn giản: sau khi mutex bị khóa bạn chỉ có thể trở lại queue_.size() (và mlock destructor phát hành các mutex) – marom

+0

@marom cảm ơn, đã sửa mã của tôi. Lỗi vẫn còn đó. – Anthea

+0

Hai điều: isEmpty và kích thước có thể không được công khai. Bất cứ điều gì họ báo cáo có thể không hợp lệ khi được người gọi đánh giá. Trừ khi chúng được sử dụng riêng tư, chúng sẽ bị loại bỏ. – stefan

Trả lời

0

Hãy thử di chuyển 'thử' lên (như trong ví dụ dưới đây). Nếu luồng của bạn đang chờ dữ liệu (bên trong waitList.pop()) thì có thể đợi bên trong biến điều kiện .wait(). Đây là một 'điểm gián đoạn' và do đó có thể ném khi chuỗi bị gián đoạn.

void MyManager::worker() 
{ 
    while (true) 
    { 
     try 
     { 
      int current = waitingList.pop(); 
      Object * p = objects.at(current); 
      p->calculateMesh(); //this task is internally locked by a mutex 

      boost::this_thread::interruption_point(); 
     } 
     catch (const boost::thread_interrupted&) 
     { 
      // Thread interruption request received, break the loop 
      std::cout << "- Thread interrupted. Exiting thread." << std::endl; 
      break; 
     } 
    } 
} 
+0

đã thử nó, nhưng lỗi vẫn còn đó. Tôi đang cập nhật câu hỏi với danh sách cuộc gọi gỡ lỗi của sự cố. – Anthea

+1

Tôi muốn quấn toàn bộ vòng lặp vào một mệnh đề try-catch-. Nó sẽ không thay đổi bất cứ điều gì ở đây, nhưng điểm rất ngoại lệ là chúng đi qua tất cả các cấu trúc dòng điều khiển như vòng lặp, do đó bạn không phải làm điều đó một cách thủ công. –

-2

Tôi nghĩ đây là vấn đề kinh điển của luồng trình đọc/ghi làm việc trên bộ đệm chung. Một trong những cách bảo mật nhất để giải quyết vấn đề này là sử dụng mutexes và tín hiệu (Tôi không thể đăng mã ở đây. Vui lòng gửi cho tôi một email, tôi đăng mã cho bạn).

0

Có thể bạn đang bắt nhầm lớp ngoại lệ? Điều đó có nghĩa là nó không bị bắt. Không quá quen thuộc với chủ đề nhưng nó là sự pha trộn của std :: chủ đề và tăng :: chủ đề đó gây ra điều này?

Thử bắt ngoại lệ gốc thấp nhất.

3

Từ kinh nghiệm của tôi về làm việc với các chủ đề trong cả Boost và Java, cố gắng tắt các chủ đề bên ngoài luôn luôn lộn xộn. Tôi chưa bao giờ có thể thực sự làm việc đó một cách sạch sẽ.

Điều tốt nhất tôi đã nhận là có giá trị boolean có sẵn cho tất cả chuỗi tiêu đề được đặt thành true. Khi bạn đặt nó thành false, các luồng sẽ tự động trở lại. Trong trường hợp của bạn, điều đó có thể dễ dàng được đưa vào vòng lặp while bạn có.

Trên hết, bạn sẽ cần một số đồng bộ hóa để bạn có thể đợi các luồng trả lại trước khi xóa chúng, nếu không bạn có thể khó xác định hành vi.

Một ví dụ từ một dự án trước đây của tôi:

Chủ đề tạo

barrier = new boost::barrier(numOfThreads + 1); 
threads = new detail::updater_thread*[numOfThreads]; 

for (unsigned int t = 0; t < numOfThreads; t++) { 
    //This object is just a wrapper class for the boost thread. 
    threads[t] = new detail::updater_thread(barrier, this); 
} 

Chủ đề phá hủy

for (unsigned int i = 0; i < numOfThreads; i++) { 
    threads[i]->requestStop();//Notify all threads to stop. 
} 

barrier->wait();//The update request will allow the threads to get the message to shutdown. 

for (unsigned int i = 0; i < numOfThreads; i++) { 
    threads[i]->waitForStop();//Wait for all threads to stop. 
    delete threads[i];//Now we are safe to clean up. 
} 

Một số phương pháp mà bạn có thể quan tâm từ các wrapper chủ đề.

//Constructor 
updater_thread::updater_thread(boost::barrier * barrier) 
{ 
    this->barrier = barrier; 
    running = true; 

    thread = boost::thread(&updater_thread::run, this); 
} 

void updater_thread::run() { 
    while (running) { 
     barrier->wait(); 
     if (!running) break; 

     //Do stuff 

     barrier->wait(); 
    } 
} 

void updater_thread::requestStop() { 
    running = false; 
} 

void updater_thread::waitForStop() { 
    thread.join(); 
} 

 

Các vấn đề liên quan