2010-08-10 38 views
5

Tôi cần phải tạo một hàm gắn thêm một giá trị vào vectơ và trả về chỉ mục của giá trị vừa được nối.Nguyên lý std :: vector :: push_back() và chỉ số trả về

Ví dụ:

int append(std::vector<int>& numbers, int number){ 
    int retval = numbers.size(); 
    // what if some other thread calls push_back(number) in between these calls? 
    numbers.push_back(number); 
    return retval; 
} 

Tôi muốn làm điều này nguyên tử để các chỉ số trở lại phải lúc nào cũng đúng ngay cả khi có thể có nhiều chủ đề phụ thêm giá trị cho vector. Sẽ dễ dàng hơn nếu push_back trả lại chỉ mục của mục vừa được thêm vào. Làm cách nào tôi có thể đảm bảo rằng chỉ mục chính xác được trả về?

+5

Thực ra, sẽ không dễ nếu push_back() trả về một chỉ mục, vì push_back() không phải là chủ đề an toàn –

+0

Bạn cần bảo vệ vùng chứa của mình khỏi tất cả các ghi đồng thời. Đồng thời push_back() đã cần đồng bộ hóa bên ngoài vector –

+3

Ghi nhớ rằng đối với nhiều ứng dụng trong thế giới thực, làm cho các hoạt động an toàn luồng nhỏ không phải là giải pháp đúng: bạn nên cân nhắc việc bảo vệ các đoạn mã lớn hơn.Bộ sưu tập chủ đề an toàn là tốt nếu bạn đang sử dụng chúng như một cơ chế truyền thông. Điều đó nói rằng, điều này cũng có thể là một trường hợp như vậy. –

Trả lời

11

std::vector không có hỗ trợ chuỗi được tạo sẵn. Bạn có thể sử dụng boost::mutex để mở rộng:

int append(std::vector<int>& numbers, int number){ 
    boost::mutex::scoped_lock slock(my_lock); 
    int retval = numbers.size(); 
    numbers.push_back(number); 
    return retval; 
} 

Bạn cần bảo vệ mọi hoạt động đọc/ghi theo cách như vậy. Một cách khác là tạo lớp bao bọc cho std::vector để mở rộng nó với hỗ trợ luồng. Kiểm tra câu hỏi this để biết chi tiết.

+1

Làm thế nào để làm việc này khi một sợi khác làm điều gì đó với véc tơ khác hơn là gọi chức năng này? Một thread khác gọi number.clear() sẽ không tôn trọng scoped_lock ở đây. –

+0

Điều này sẽ hoạt động, nhưng nó sẽ chỉ đảm bảo hoạt động duy nhất này. Bất cứ ai cũng có thể làm một 'push_back()' ở một nơi khác trên cùng một đối tượng và làm cho nó bị hỏng. – sharptooth

+4

Cần bảo vệ mọi hoạt động đọc/ghi. Có thể OP nên tạo lớp wrapper cho 'std :: vector' để mở rộng nó với sự hỗ trợ luồng. Kiểm tra câu hỏi [this] (http://stackoverflow.com/questions/1099513/threadsafe-vector-class-for-c) để biết chi tiết. –

3

Vùng chứa STL không an toàn chỉ (ngay cả khi chỉ gọi tới số push_back()), bạn sẽ phải tự giải quyết vấn đề này - sử dụng một số nguyên tắc đồng bộ hóa phù hợp bên ngoài STL.

0

Bạn cần phải sử dụng một mutex để đảm bảo rằng các chỉ số chính xác sẽ được trả về

+0

Đây thực sự là một bình luận, không phải là câu trả lời cho câu hỏi. Vui lòng sử dụng "thêm nhận xét" để để lại phản hồi cho tác giả. –

+2

Không đồng ý. Tôi tin rằng đây là một câu trả lời. Câu trả lời được chấp nhận cũng đưa ra lời khuyên tương tự nhưng với một ví dụ. –

0

Các giải pháp mạnh bảo là để khóa toàn bộ vector trên tất cả các hoạt động đó (có nghĩa là kiểm soát mỗi hoạt động từ khắp mọi nơi trong các mã , điều đó thực sự có nghĩa là tạo ra một vector đồng bộ).

Nó có thể là một cái gì đó đơn giản như điều này sẽ làm cho các mục đích của bạn:

int append(std::vector<int>& numbers, int number){ 
    int retval = numbers.size(); 
    // what if some other thread calls push_back(number) in between these calls? 
    numbers.push_back(number); 
    int newSize = numbers.size(); 
    //this bit is as a short-cut in common, easy, cases 
    if(newSize = retval + 1) //no need for further complication 
    return retval; 
    while(++retval < newSize) 
    if(numbers[retval] == number) 
     return retval; 
    //If we get this far, numbers have been deleted, not added. More discussion below. 
} 

Một điều về vấn đề này là nếu chủ đề đẩy 3, 3, 3, 3 sau đó chỉ số trở lại sẽ là sai lầm, mặc dù nó vẫn sẽ là một chỉ mục cho 3. Cho dù đó là okay hay không phụ thuộc vào mục đích của bạn. Một điều nữa là nếu véc tơ bị xuất hiện hoặc bị rút ngắn trong thời gian chờ đợi, thì tốt nhất là chúng tôi sẽ đưa ra nhận xét trong đoạn mã ở trên, tệ hơn là lỗi (khi chúng bật lại sau khi chúng tôi nhận được newSize và sau đó truy cập [retval] trở thành không hợp lệ). Bạn cần phải xem xét nếu trường hợp này có thể xảy ra (có thể bạn biết từ phần còn lại của mã mà nó sẽ không bao giờ) và phải làm gì nếu nó xảy ra.

Nếu các giới hạn này quá lớn đối với trường hợp sử dụng của bạn, thì việc tạo ra một vectơ được đồng bộ hóa hoàn toàn là điều tốt nhất tôi có thể nghĩ là tôi sợ.

2

Trong Visual Studio 2010, bạn có thể sử dụng một concurrent_vector cho việc này, nó cung cấp chức năng phát triển đồng bộ. This topic liệt kê từng vùng chứa đồng thời.

Lưu ý rằng chúng cũng có sẵn trong TBB của Intel với cú pháp giống hệt nhau + ngữ nghĩa và như vậy là nền tảng có sẵn.

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