2012-02-27 17 views
6
static pthread_mutex_t gLock; //global 

pthread_mutex_init(&gLock,NULL); //in init 

pthread_mutex_lock(&gLock); 
for(int i=0;i<[message count];i++) 
CFSetAddValue(mSet, [message objectAtIndex:i]); 
pthread_mutex_unlock(&gLock); 

Ứng dụng ca cao của tôi đang ở chế độ không phản hồi với pthread_mutex_t.pthread_mutex_t VS @synchronized block?

@synchronized(mSet) 
{ 
for(int i=0;i<[message count];i++) 
    CFSetAddValue(mSet, [message objectAtIndex:i]); 
} 

Ứng dụng của tôi đang hoạt động tốt với khối được đồng bộ hóa.

Tại sao?

Trả lời

8

Bạn đang so sánh khóa toàn cầu (một khóa cho tất cả các phiên bản) với khóa đệ quy cấp đối tượng (một khóa cho mỗi thể hiện, có thể được mua nhiều lần từ cùng một chuỗi). Chúng thường không thể hoán đổi cho nhau - chúng hoạt động và bảo vệ rất khác nhau.

Tin vui là, bạn có thể sử dụng pthread_mutex_t làm khóa đệ quy, duy nhất cho từng trường hợp để đạt được cùng mức độ bảo vệ như @synchronized. Sử dụng pthread_mutex_t cũng làm cho việc mua lại khóa nhiều, nhanh hơn nhiều.

Để đạt được hiệu ứng tương tự như @synchronized bằng cách sử dụng một mutex pthread, hãy khai báo pthread_mutex_t gLock làm biến mẫu, sau đó khởi tạo nó dưới dạng một mutex đệ quy trong -init. Cuối cùng, phá hủy mutex trong -dealloc.

Tất nhiên, các lớp phụ và cơ sở có thể cần truy cập vào khóa này nếu chúng dựa vào ngữ nghĩa của @synchronized để làm điều đúng thông qua phân cấp đối tượng.

@synchronized là chậm hơn so với một mutex đệ quy pthread (cuối cùng tôi đã kiểm tra).

+1

Trong tệp .h \t pthread_mutexattr_t attr; \t pthread_mutex_t mutex; trong init \t \t pthread_mutexattr_settype (& attr, PTHREAD_MUTEX_RECURSIVE); \t \t pthread_mutex_init (& mutex, &attr); trong dealloc pthread_mutex_destroy (& mutex); chức năng pthread_mutex_lock của tôi (& mutex); \t \t \t \t CFSetRemoveAllValues ​​(mySet); \t \t \t pthread_mutex_unlock (& ​​mutex); là Khoản tiền này? –

+1

@ParagBafna a) attex mutex có thể là 'static' và được sử dụng cho mọi mutex bạn tạo - hoặc không tĩnh và chỉ được sử dụng trong' -init' b) mutex attr không cần phải là ivar c) bạn nên xác minh mã kết quả d) bạn cũng có thể thích 'pthread_mutex_trylock' trong một số trường hợp. e) bạn nên khởi tạo các cấu trúc bằng cách sử dụng initializers. Khác hơn thế, có vẻ tốt! chuẩn bị cho khóa nhanh =) – justin

+0

mã kết quả hữu ích chủ yếu để phát hiện lỗi khóa và luồng. – justin

0

Justin là đúng; đó cũng là một chi tiết khác, tuy nhiên, đó là xử lý ngoại lệ. Từ https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html đến mẹo này:

Như một biện pháp phòng ngừa, khối @synchronized ngầm cho biết thêm một exception handler vào mã bảo vệ. Trình xử lý này tự động giải phóng mutex trong trường hợp ngoại lệ được ném. Điều này có nghĩa là để sử dụng chỉ thị @synchronized, bạn cũng phải bật xử lý ngoại lệ Objective-C trong mã của bạn. Nếu bạn không muốn chi phí bổ sung gây ra bởi trình xử lý ngoại lệ ẩn, bạn nên cân nhắc việc sử dụng các lớp khóa.

Nếu [message count] có thể tăng các ngoại lệ có thể nhảy qua mã mở khóa của bạn và nêm bạn lên.

+0

… nếu bạn có thể phục hồi. hầu hết các trường hợp ngoại lệ ca cao không thể phục hồi (ít nhất, nếu bạn muốn thực hiện dự đoán sau đó). trường hợp phổ biến cho một ngoại lệ có thể phục hồi sẽ là C++ (phục hồi có thể dự đoán được). – justin