Điều tương tự cũng áp dụng cho từ điển? Hoặc là một từ điển một tập hợp các biến?
Hãy là tổng quát hơn:
gì "hoạt động nguyên tử" nghĩa là gì?
Từ Wikipedia:
Trong lập trình đồng thời, một hoạt động (hay tập hợp các hoạt động) là nguyên tử, linearizable, tách hoặc liên tục nếu nó xuất hiện ở phần còn lại của hệ thống để xảy ra ngay lập tức. Nguyên tử là một sự bảo đảm của sự cách ly tách biệt khỏi các quá trình đồng thời.
Bây giờ điều này có ý nghĩa gì trong Python?
Điều này có nghĩa là mỗi lệnh bytecode là nguyên tử (ít nhất là đối với Python < 3.2, trước GIL mới).
Tại sao lại như vậy ???
Vì Python (CPython) sử dụng Global Interpreter Lock (GIL). Trình thông dịch CPython sử dụng khóa để đảm bảo chỉ có một chuỗi chạy trong trình thông dịch tại một thời điểm và sử dụng "khoảng thời gian kiểm tra" (xem sys.getcheckinterval()
) để biết số lượng lệnh bytecode thực thi trước khi chuyển đổi giữa các chuỗi (theo mặc định được đặt thành 100).
Vì vậy, bây giờ điều này có nghĩa là gì ??
Điều đó có nghĩa là các phép toán có thể được biểu diễn bởi chỉ một lệnh bytecode là nguyên tử. Ví dụ, incrementing một biến là không nguyên tử, bởi vì các hoạt động được thực hiện trong ba hướng dẫn bytecode:
>>> import dis
>>> def f(a):
a += 1
>>> dis.dis(f)
2 0 LOAD_FAST 0 (a)
3 LOAD_CONST 1 (1) <<<<<<<<<<<< Operation 1 Load
6 INPLACE_ADD <<<<<<<<<<<< Operation 2 iadd
7 STORE_FAST 0 (a) <<<<<<<<<<<< Operation 3 store
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
Vì vậy, những gì về các từ điển ??
Một số hoạt động là nguyên tử; ví dụ, hoạt động này là nguyên tử:
d[x] = y
d.update(d2)
d.keys()
Xem cho chính mình:
>>> def f(d):
x = 1
y = 1
d[x] = y
>>> dis.dis(f)
2 0 LOAD_CONST 1 (1)
3 STORE_FAST 1 (x)
3 6 LOAD_CONST 1 (1)
9 STORE_FAST 2 (y)
4 12 LOAD_FAST 2 (y)
15 LOAD_FAST 0 (d)
18 LOAD_FAST 1 (x)
21 STORE_SUBSCR <<<<<<<<<<< One operation
22 LOAD_CONST 0 (None)
25 RETURN_VALUE
Xem this để hiểu những gì STORE_SUBSCR làm.
Nhưng như bạn thấy, nó không phải là hoàn toàn đúng, bởi vì hoạt động này:
...
4 12 LOAD_FAST 2 (y)
15 LOAD_FAST 0 (d)
18 LOAD_FAST 1 (x)
...
có thể làm cho toàn bộ hoạt động không nguyên tử. Tại sao? Giả sử biến x cũng có thể được thay đổi bởi một chuỗi khác ... hoặc bạn muốn một chuỗi khác xóa từ điển của bạn ... chúng tôi có thể đặt tên cho nhiều trường hợp khi nó có thể sai, vì vậy nó phức tạp! Và vì vậy ở đây chúng tôi sẽ áp dụng Murphy's Law: "Bất cứ điều gì có thể đi sai, sẽ đi sai".
Vậy bây giờ là gì?
Nếu bạn vẫn muốn chia sẻ biến giữa chủ đề, sử dụng một khóa:
import threading
mylock = threading.RLock()
def atomic_operation():
with mylock:
print "operation are now atomic"
Thật vậy.Và nên N và M sẽ sửa đổi dữ liệu ['a'] sẽ xảy ra, nhưng nếu chủ đề N sửa đổi dữ liệu ['a'] và luồng M sửa đổi dữ liệu ['b'] thì sao? Điều đó vẫn còn xảy ra? Và những gì có thể được thực hiện mà không cần khóa từ điển? – skerit
@skerit: Như tôi đã viết, không. Họ không can thiệp lẫn nhau. Tất nhiên bạn không thể chắc chắn rằng họ thực sự không bao giờ chồng chéo nếu họ chia sẻ từ điển ... – delnan
Ồ đúng, tôi hiểu rồi. "một vị trí trong từ điển". Sau đó, tôi chỉ phải khóa từ điển khi thêm hoặc xóa một khóa, vì điều đó sẽ gây ra ngoại lệ khi có thứ gì đó đang lặp qua nó. – skerit