2011-12-13 27 views
5

Tôi có một Máy chủ Web chạy trong Python. Máy chủ là riêng tư, vì vậy tôi chỉ mong đợi khoảng 20 người dùng kết nối với nó. Các máy chủ là đa luồng (8 lõi tại thời điểm này, vì vậy 8 chủ đề tôi đoán).Làm thế nào để bạn thực hiện điều này từ điển Python an toàn?

Khi có yêu cầu, tôi có thể xác định người dùng. Trên một số truy vấn, tôi cần phải cập nhật đơn giản dictionary của biểu mẫu tên người dùng -> Boolean. Làm thế nào tôi có thể làm cho một sợi này an toàn?

+0

Bạn đang tự mình triển khai máy chủ hay bạn đang sử dụng thứ gì đó như django, kim tự tháp hoặc xoắn? – dirk

+0

Đó là cherrypy, phiên bản 3.2 – Jerome

Trả lời

5

Nếu bạn cần một khóa (để tránh những điều kiện chủng tộc Joonas mô tả), và đang bị mắc kẹt với Python 2.4,

import threading 
lock = threading.Lock() 

shared_dict = {} 

def do_thing(user, value): 
    lock.acquire() 
    try: 
     shared_dict[user] = value 
    finally: 
     # Always called, even if exception is raised in try block 
     lock.release() 
+0

giả sử nhà văn của tôi kết thúc các sửa đổi của nó trong khóa đó. Người đọc sẽ chờ cho đến khi điều này được phát hành, tức là văn bản đã kết thúc? Hay tôi cần phải quấn những lần đọc trong đó? – Jerome

+0

@jeromeG bạn có thể cần phải có một chức năng khóa tương tự để đọc (một lần nữa chỉ để tránh điều kiện cuộc đua "đọc-sửa-viết") – dbr

2

Sử dụng threading.LOCK.acquire() trước khi cập nhật từ điển và sử dụng luồng.LOCK.release(), sau khi bạn cập nhật xong.

+0

Điều này là lạ, tôi đã có thể mong đợi các đối tượng khóa được cụ thể cho từ điển, một chút giống như một đối tượng đồng bộ/khối/phương pháp trong Java ... Tôi đang bối rối – Jerome

8

Bạn cần phải tạo đối tượng khóa chung.

lock = threading.Lock() 

Sau đó, xung quanh mỗi quyền truy cập của từ điển có được và nhả khóa. Cách đơn giản nhất để làm điều này là với (ish) with syntax mới.

with lock: 
    dict[key] = value 
+0

tôi bị giới hạn việc sử dụng Python 2.4, có phải là không khả dụng không? – Jerome

+0

Không, không có sẵn, nhưng bạn có thể sử dụng lock.acquire() và lock.release(). –

4

Bạn có thể hoặc không cần sử dụng khóa, tùy thuộc vào cách Boolean được cập nhật.

Nếu giá trị của Booleankhông phụ thuộc vào giá trị trước đó của nó, sau đó không khóa là cần thiết: viết và đọc một cuốn từ điển Python là thread-an toàn bằng cách riêng của mình (ngoại trừ: writing while iterating is not allowed - nhưng điều đó không được phép vào đơn thread). Khả năng hiển thị bộ nhớ tương tự như những gì sẽ đạt được bằng cách sử dụng volatile ở một số ngôn ngữ.

Điều vốn dĩ không an toàn chỉ là kết quả "đọc-sửa-ghi", dẫn đến tình trạng cuộc đua. Nếu giá trị của Booleankhông phụ thuộc vào giá trị trước đó, thì bạn phải sử dụng khóa, vì nếu không luồng A trước tiên có thể đọc giá trị, thì chuỗi B có thể thay đổi, và sau đó A sẽ thay đổi lại, dựa trên giá trị lỗi thời để bắt đầu.

0

Bạn đừng cần phải khóa từ điển để hoạt động này, bởi vì hoạt động này là nguyên tử và GIL chăm sóc điều này cho bạn. Trừ khi bạn có các hoạt động như đọc-thay đổi-viết, đừng lo lắng.

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