2012-11-06 40 views
5

Dường như vì truy cập vào dữ liệu mảng NumPy không yêu cầu các cuộc gọi vào trình thông dịch Python, phần mở rộng C có thể thao tác các mảng sau khi phát hành GIL. Ví dụ: trong this thread.Truy cập đa luồng vào Python bytearray

Việc xây dựng trong Python loại bytearray hỗ trợ Buffer Protocol, một thành viên trong số đó là

trống * buf

Một con trỏ đến đầu của cấu trúc logic được mô tả bởi các lĩnh vực đệm . [...] Đối với các mảng tiếp giáp, giá trị trỏ đến phần đầu của bộ nhớ khối.

Câu hỏi của tôi là, một phần mở rộng C có thể thao tác này buf sau khi phát hành GIL (Py_BEGIN_ALLOW_THREADS) kể từ khi truy cập vào nó không còn đòi hỏi các cuộc gọi đến các API Python C? Hay bản chất của trình thu gom rác Python cấm điều này, vì dấu ngắt quãng và buf của nó, có thể được di chuyển trong khi thực hiện?

+1

Cấu trúc 'Py_buffer' giữ tham chiếu và không thể thay đổi kích thước' bytearray' cho đến khi tất cả xuất bộ đệm đã được giải phóng (tức là trong khi 'ob_exports> 0'). – eryksun

+0

Cảm ơn - và tôi lấy điều đó để có nghĩa là quá rằng buf sẽ không được di chuyển (trái ngược với phát hành) bởi GC trong khi bộ đệm được xuất khẩu? Liệu Python có sử dụng [GC chuyển động] (http://en.wikipedia.org/wiki/Garbage_collection_ (computer_science) # Moving_vs._non-moving) không? – jpavel

+0

'bytearray' được deallocated khi số tham chiếu đạt 0. Python cố gắng GC để giải quyết chu kỳ tham chiếu trong các loại container (ví dụ: danh sách, các lớp). – eryksun

Trả lời

3

Để làm rõ câu trả lời ngắn được viết dưới dạng chú thích: bạn có thể truy cập dữ liệu * buf mà không giữ GIL, miễn là bạn chắc chắn rằng cấu trúc Py_buffer được "sở hữu" bởi chuỗi trong khi nó đang chạy mà không có GIL.

Vì mục đích hoàn chỉnh, tôi nên thêm rằng điều này có thể mở cửa đến (rất từ ​​xa) các nguy cơ bị treo: nếu chuỗi GIL-ít đọc dữ liệu tại * buf trong khi đồng thời một chuỗi giữ GIL khác chạy mã Python thay đổi cùng một dữ liệu (bytearray [index] = x) thì chuỗi GIL-less có thể thấy các thay đổi bất ngờ của dữ liệu dưới chân nó. Điều ngược lại cũng đúng, và thậm chí còn khó chịu hơn (nhưng vẫn lý thuyết): nếu chuỗi GIL-ít thay đổi dữ liệu tại * buf, thì GIL-holding khác, chuỗi chạy Python có thể thấy kết quả lạ hoặc thậm chí có thể bị treo nếu thực hiện một số các hoạt động đọc phức tạp như bytearray.split().