2010-09-03 36 views
5

tôi gặp sự cố với thứ tự thực hiện các chuỗi được tạo liên tục. đây là mã.boost :: đề xuất thực hiện yêu cầu

#include <iostream> 
#include <Windows.h> 
#include <boost/thread.hpp> 

using namespace std; 

boost::mutex mutexA; 
boost::mutex mutexB; 
boost::mutex mutexC; 
boost::mutex mutexD; 


void SomeWork(char letter, int index) 
{ 
    boost::mutex::scoped_lock lock; 
    switch(letter) 
    { 
    case 'A' : lock = boost::mutex::scoped_lock(mutexA); break; 
    case 'B' : lock = boost::mutex::scoped_lock(mutexB); break; 
    case 'C' : lock = boost::mutex::scoped_lock(mutexC); break; 
    case 'D' : lock = boost::mutex::scoped_lock(mutexD); break; 
    } 

    cout << letter <<index << " started" << endl; 
    Sleep(800); 
    cout << letter<<index << " finished" << endl; 
} 

int main(int argc , char * argv[]) 
{ 
    for(int i = 0; i < 16; i++) 
    { 
     char x = rand() % 4 + 65; 
     boost::thread tha = boost::thread(SomeWork,x,i); 
     Sleep(10); 
    } 
Sleep(6000); 
    system("PAUSE"); 
    return 0; 
} 

mỗi lần một chữ cái (từ A đến D) và id chi (i) được chuyển cho phương thức SomeWork làm chuỗi. tôi không quan tâm về thứ tự thực hiện giữa các chữ cái nhưng đối với một lá thư prticular, nói A, Ax phải bắt đầu trước khi Ay, nếu x < y. một phần ngẫu nhiên của một đầu ra ngẫu nhiên của mã là:

 
B0 started 
D1 started 
C2 started 
A3 started 
B0 finished 
B12 started 
D1 finished 
D15 started 
C2 finished 
C6 started 
A3 finished 
A9 started 
B12 finished 
B11 started --> B11 started after B12 finished. 
D15 finished 
D13 started 
C6 finished 
C7 started 
A9 finished 

làm cách nào để tránh các điều kiện như vậy?
cảm ơn.


tôi đã giải quyết vấn đề bằng cách sử dụng các biến điều kiện. nhưng tôi đã thay đổi vấn đề một chút. giải pháp là theo dõi chỉ số vòng lặp for. do đó, mỗi thread biết khi nào nó không hoạt động. nhưng theo như mã này là có liên quan, có hai điều khác mà tôi muốn hỏi về.
trước tiên, trên máy tính của tôi, khi tôi đặt chỉ số vòng lặp thành 350 tôi đã vi phạm quyền truy cập. 310 là số vòng lặp, là ok. vì vậy tôi nhận ra rằng có một số lượng tối đa các luồng được tạo ra. làm thế nào tôi có thể xác định con số này? giây, trong phòng thu trực quan 2008, phiên bản phát hành của mã cho thấy một hành vi thực sự kỳ lạ. mà không sử dụng biến điều kiện (dòng 1 đến 3 đã được nhận xét), các chủ đề đã được sắp xếp. làm thế nào điều đó có thể xảy ra?

đây là mã:

#include <iostream> 
#include <Windows.h> 
#include <boost/thread.hpp> 

using namespace std; 

boost::mutex mutexA; 
boost::mutex mutexB; 
boost::mutex mutexC; 
boost::mutex mutexD; 


class cl 
{ 
public: 
    boost::condition_variable con; 
    boost::mutex mutex_cl; 
    char Letter; 
    int num; 
    cl(char letter) : Letter(letter) , num(0) 
    { 

    } 
    void doWork(int index, int tracknum) 
    { 
     boost::unique_lock<boost::mutex> lock(mutex_cl); 
     while(num != tracknum)  // line 1 
      con.wait(lock); // line 2 
     Sleep(10); 
     num = index; 
     cout << Letter<<index << endl; 
     con.notify_all(); // line 3 
    } 
}; 

int main(int argc , char * argv[]) 
{ 
    cl A('A'); 
    cl B('B'); 
    cl C('C'); 
    cl D('D'); 

    for(int i = 0; i < 100; i++) 
    { 
     boost::thread(&cl::doWork,&A,i+1,i); 
     boost::thread(&cl::doWork,&B,i+1,i); 
     boost::thread(&cl::doWork,&C,i+1,i); 
     boost::thread(&cl::doWork,&D,i+1,i); 
    } 
    cout << "************************************************************************" << endl; 

    Sleep(6000); 
    system("PAUSE"); 
    return 0; 
} 

Trả lời

6

Nếu bạn có hai chủ đề khác nhau chờ đợi khóa, nó hoàn toàn không xác định cái nào sẽ có được nó khi khóa được phát hành bởi người giữ trước. Tôi tin rằng đây là những gì bạn đang trải qua. Giả sử B10 đang giữ khóa và trong các chuỗi thời gian trung bình được sinh ra cho B11B12. B10 giải phóng khóa - xuống đến một đồng xu quăng về việc liệu B11 hoặc B12 có được tiếp theo không, bất kể chuỗi nào đã được tạo đầu tiên hoặc thậm chí chuỗi nào bắt đầu chờ trước.

Có lẽ bạn nên triển khai hàng đợi công việc cho mỗi chữ cái, sao cho bạn sinh ra chính xác 4 luồng, mỗi chuỗi tiêu thụ đơn vị công việc? Đây là cách duy nhất để dễ dàng đảm bảo đặt hàng theo cách này. Một mutex đơn giản sẽ không đảm bảo sắp xếp nếu nhiều luồng đang đợi khóa.

+0

ý của các đơn vị công việc là gì? –

+0

Một số biểu diễn của một tác phẩm sẽ được thực hiện bởi một chuỗi. Trong trường hợp này, một đơn vị làm việc về cơ bản sẽ là một cặp '(thư, chỉ mục)'. – Gian

2

Mặc dù B11 được khởi động trước B12 nhưng không đảm bảo được cung cấp một lát thời gian CPU để thực thi SomeWork() trước B12. Quyết định này tùy thuộc vào hệ điều hành và trình lên lịch của nó.

Mutex thường được sử dụng để đồng bộ hóa quyền truy cập vào dữ liệu giữa các luồng và mối quan ngại đã được nâng lên với chuỗi thực thi luồng (tức là truy cập dữ liệu).

Nếu chủ đề cho nhóm 'A' đang thực thi cùng một mã trên cùng một dữ liệu thì chỉ cần sử dụng một chuỗi. Điều này sẽ loại bỏ bối cảnh chuyển đổi giữa các chủ đề trong nhóm và mang lại kết quả tương tự. Nếu dữ liệu đang thay đổi, hãy xem xét một mẫu nhà sản xuất/người tiêu dùng. Paul Bridger cho dễ hiểu nhà sản xuất/ví dụ tiêu dùng here.

1

Chủ đề của bạn có các phụ thuộc phải được thỏa mãn trước khi bắt đầu thực thi. Trong ví dụ của bạn, B12 phụ thuộc vào B0 và B11. Bằng cách nào đó bạn phải theo dõi kiến ​​thức phụ thuộc đó. Chủ đề với phụ thuộc chưa hoàn thành phải được thực hiện để chờ đợi.

Tôi sẽ xem xét condition variables. Mỗi khi một luồng kết thúc SomeWork() nó sẽ sử dụng phương thức notify_all() của biến điều kiện. Sau đó, tất cả các chủ đề chờ đợi phải kiểm tra xem họ vẫn còn phụ thuộc. Nếu có, hãy quay lại và chờ đợi. Nếu không, hãy tiếp tục và gọi SomeWork().

Bạn cần một số cách cho mỗi chuỗi để xác định xem nó có phụ thuộc chưa hoàn thành hay không. Điều này có thể sẽ là một số thực thể có sẵn trên toàn cầu. Bạn chỉ nên sửa đổi nó khi bạn có mutex (trong SomeWork()). Đọc theo nhiều chủ đề nên an toàn cho các cấu trúc dữ liệu đơn giản.

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