2010-10-28 45 views
8

Có cách nào trong mục tiêu C mà tôi có thể định nghĩa một static int đó là thread an toàn không?Chủ đề an toàn biến tĩnh mục tiêu c

ví dụ nếu tôi có lớp được gọi là phiên có:

static unsigned int session_id = 1000; 

- (int) generateSessionID{ 
     return session_id++; 
} 

Tôi đang xây dựng đối tượng phiên từ chủ đề khác nhau, mỗi đối tượng session nên có một id duy nhất.

+0

Bạn cần sử dụng một số loại ngữ nghĩa khóa. Vấn đề là bạn muốn hoạt động là nguyên tử. Nhưng hãy nhớ rằng "++" không phải là nguyên tử chút nào, nó là một vài thao tác cùng một lúc. – BobbyShaftoe

+0

có thể sau đó bao quanh session_id ++ trả về của tôi với (self) {return session_id ++} được đồng bộ hóa. Tuy nhiên tôi không chắc chắn nếu điều này sẽ khóa lớp hoặc đối tượng nó tự. – Unis

+0

như được viết, nó sẽ khóa các trường hợp, không phải là lớp học (không phải những gì bạn muốn). Có lẽ "' @synchronized ([self class]) '"? –

Trả lời

4

Nếu bạn đang nói Cocoa, chức năng mutex được cung cấp bởi NSLockNSRecursiveLock.

Để bảo vệ đúng tài nguyên không nguyên tử, bạn cần những mutexes này, vì sợ nhiều chủ đề có thể cố gắng thay đổi dữ liệu cùng một lúc (dẫn đến tham nhũng) hoặc sử dụng dữ liệu ở trạng thái thay đổi một nửa (dẫn đến dữ liệu không hợp lệ).

Mã của bạn sẽ giống như thế này:

static NSLock session_id_lock; 
static unsigned int session_id = 1000; 

- (int) generateSessionID{ 
    int new_id; 
    [myLock lock]; 
    new_id = session_id++; 
    [myLock unlock]; 
    return new_id; 
} 

Nếu bạn không sử dụng Cocoa (hoặc những gì ít Cocoa lập trình Tôi nhớ từ Interlude ngắn gọn của tôi với một iMac được rất lờ mờ nhớ ra rằng nó gần vô dụng) , chỉ cần sử dụng khái niệm, dịch nó sang bất kỳ ngôn ngữ hoặc khuôn khổ nào bạn có:

  • khóa mutex trước khi sử dụng hoặc thay đổi tài nguyên được bảo vệ.
  • sử dụng hoặc thay đổi tài nguyên.
  • mở khóa mutex.
  • lời khuyên về tiền thưởng 1: khóa mutex càng sớm càng tốt và mở khóa càng sớm càng tốt.
  • lời khuyên bổ sung 2: chỉ khóa những gì bạn cần để tránh những sự chậm trễ không cần thiết.

Giải thích rằng điểm cuối cùng một số khác: nếu bạn đồng bộ hóa trên self cho hai thứ hoàn toàn không liên quan (nói ID phiên và ID người dùng), chúng sẽ chặn nhau mặc dù thực tế là không cần thiết. Tôi muốn hai mutexes riêng biệt để giữ mức độ chi tiết thấp.

Tất nhiên, nếu bạn chỉ có một mutex trên ID phiên (nhưng xem bên dưới để báo trước), hãy sử dụng synchronized(self) nhưng tôi muốn làm theo cách của mình vì vậy tôi sẽ không bị phát hiện thêm một tài nguyên được bảo vệ khác sau đó.

Trong mọi trường hợp (đây là báo trước được đề cập), có thể bạn sẽ thấy rằng việc đồng bộ hóa trên self sẽ không bảo vệ đầy đủ biến tĩnh, sẽ được chia sẻ trên nhiều đối tượng. Các mutex nên thuộc về các dữ liệu hơn là bất cứ điều gì đang sử dụng nó.

+0

Tôi đến từ thế giới Java, nơi bạn có thể thực hiện: static generate int generateID() {return sessionId ++}. là điều này sẽ tương thích nếu tôi làm - (int) generateSessionID {sync (self) {return session_id ++;}}? – Unis

+0

Tôi sẽ nghĩ rằng sẽ làm việc ổn dù một khóa trên tự (đối tượng) có lẽ rộng hơn tôi sẽ làm. Thay vào đó, tôi muốn một mutex cụ thể để tránh sự chậm trễ mutex không cần thiết (xem lời khuyên bổ sung tiền thưởng của tôi). – paxdiablo

+0

@ user489579 Đóng, nhưng bạn không muốn đồng bộ hóa trên 'tự' cho một phương pháp thể hiện đang truy cập một biến tĩnh; có thể đồng bộ hóa trên '[self class]' hoặc trên đối tượng được liên kết trực tiếp với giá trị bạn đang sửa đổi (ví dụ: bọc int trong NSNumber và đồng bộ hóa trên NSNumber). –

8

Tôi nghĩ bạn nên sử dụng atomic operations để sửa đổi session_id. A previous question nói về các hoạt động tăng/giảm nguyên tử cho OS X và this page nói về tệp tiêu đề OSAtomic. Các hoạt động nguyên tử trên các số nguyên, một cái gì đó dễ dàng hỗ trợ phần cứng, có thể sẽ nhanh hơn đáng kể so với việc sử dụng các cấu trúc khóa.

+1

Đồng ý. Nếu tất cả những gì bạn đang làm là giữ một giá trị tĩnh cho mục đích nhận giá trị gia tăng toàn cục, hãy sử dụng 'OSAtomicIncrement32', nó sẽ an toàn và không có toàn bộ các nguyên tố đồng bộ của Cocoa hoặc POSIX. –

+1

http://developer.apple.com/library/mac/# DOCUMENTATION/Cocoa/Khái niệm/Đa luồng/ThreadSafety/ThreadSafety.html # // apple_ref/doc/uid/10000057i-CH8-SW14 – mcfedr

1

Có nhiều tùy chọn, bao gồm (từ mức cao đến thấp) chỉ thị @synchronized Mục tiêu-C, NSLock, pthread_mutex_lock và các hoạt động nguyên tử.

Đọc phần "Đồng bộ hóa" của Threading Programming Guide để biết chi tiết.

2

Trả lời 4 năm sau đó hiện có trong iOS8. : O) Điều tốt nhất đối với tôi là sử dụng một lớp singleton như sau:

(yourFile.h)

#import <Foundation/Foundation.h> 

@interface singletonSessionId : NSObject 

+ (singletonMsgNbr*)sharedSingleton; 

- (void)generateSessionId; 

@property NSInteger value; 

@end 

================= ==================================== (yourFile.m)

#import "singletonSessionId.h" 

@implementation singletonSessionId 
@synthesize value = _value; 

+ (singletonMsgNbr*)sharedSingleton { 

    static singletonSessionId *instance = nil; 

    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     instance = [[singletonSessionId alloc]init]; 
     instance.value = 1000; 
    }); 

    return instance; 
} 

- (void)generateSessionId { 
    _value += 1; 
} 

@end 

Bạn chỉ cần gọi phương thức 'generateSessionId' cho mỗi giá trị Id mới. Sử dụng lớp này để tạo Id phiên của bạn phải đủ xa tôi nghĩ.

Hy vọng nó sẽ giúp người đọc bài đăng này. : o)

+0

@ondermerol: thực sự và đó là chính xác những gì nó có nghĩa là để làm => ' Bạn chỉ cần gọi phương thức 'generateSessionId' cho mỗi giá trị Id mới '. –

+0

Xin lỗi vì câu trả lời muộn, nó hoạt động giống như một sự quyến rũ, tôi đã phạm sai lầm. – ondermerol

+1

@ XLE_22: Chủ đề này có an toàn không? Giả sử thread1 gọi generateSessionID, sau đó thread2 gọi generateSessionID trước khi thread1 đã có cơ hội để lấy giá trị? Cả hai sẽ không sử dụng cùng một id? Và nếu cả hai đều gọi phương thức cùng một lúc, thì không có tiềm năng nào cho sự tham nhũng của bộ nhớ vì không có công cụ đồng bộ hóa nào được sử dụng? – jk7

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