Câu hỏi Sự khác nhau giữa các thuộc tính nguyên tử và phi nguyên tử là gì?


Làm gì atomic và nonatomic có nghĩa là trong khai báo tài sản?

@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;

Sự khác biệt hoạt động giữa ba điều này là gì?


1723
2018-02-26 02:31


gốc


developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/… - KKendall
@ Alex Wayne - tôi có một vấn đề và tôi đã đăng nó nhưng không ai trả lời cho điều này. Vì vậy, bạn có thể giúp tôi cho điều này. Liên kết câu hỏi - stackoverflow.com/questions/35769368/… - DJ1


Các câu trả lời:


Hai cái cuối cùng giống hệt nhau; "nguyên tử" là hành vi mặc định (lưu ý rằng nó không thực sự là một từ khóa; nó chỉ được xác định bởi sự vắng mặt của nonatomic - - atomic đã được thêm dưới dạng từ khóa trong các phiên bản gần đây của llvm / clang).

Giả sử rằng bạn đang @ lồng ghép các triển khai phương thức, thay đổi nguyên tử và phi nguyên tử mã được tạo ra. Nếu bạn đang viết setter / getters của riêng bạn, nguyên tử / nonatomic / giữ lại / gán / sao chép chỉ đơn thuần là tư vấn. (Lưu ý: @synthesize bây giờ là hành vi mặc định trong các phiên bản LLVM gần đây. Cũng không cần phải khai báo các biến mẫu, chúng cũng sẽ được tổng hợp tự động và sẽ có _ được thêm vào tên của họ để ngăn chặn truy cập trực tiếp tình cờ).

Với "nguyên tử", setter / getter tổng hợp sẽ đảm bảo rằng toàn thể giá trị luôn luôn được trả về từ getter hoặc được thiết lập bởi setter, bất kể hoạt động setter trên bất kỳ thread nào khác. Đó là, nếu luồng A ở giữa getter trong khi thread B gọi setter, một giá trị thực khả thi - một đối tượng autoreleased, rất có thể - sẽ được trả về cho người gọi trong A.

Trong nonatomic, không có bảo đảm như vậy được thực hiện. Như vậy, nonatomic nhanh hơn đáng kể so với "nguyên tử".

Cái "nguyên tử" nào không phải làm là thực hiện bất kỳ đảm bảo về an toàn thread. Nếu luồng A gọi hàm getter đồng thời với chuỗi B và C gọi setter với các giá trị khác nhau, luồng A có thể lấy bất kỳ một trong ba giá trị được trả về - một trước khi bất kỳ trình lắng nghe nào được gọi hoặc một trong các giá trị được chuyển vào bộ định tuyến trong B và C. Tương tự như vậy, đối tượng có thể kết thúc với giá trị từ B hoặc C, không có cách nào để nói.

Đảm bảo tính toàn vẹn dữ liệu - một trong những thách thức chính của lập trình đa luồng - được thực hiện bằng các phương tiện khác.

Thêm vào đây:

atomicity của một thuộc tính duy nhất cũng không thể đảm bảo an toàn luồng khi nhiều thuộc tính phụ thuộc đang được phát.

Xem xét:

 @property(atomic, copy) NSString *firstName;
 @property(atomic, copy) NSString *lastName;
 @property(readonly, atomic, copy) NSString *fullName;

Trong trường hợp này, luồng A có thể đổi tên đối tượng bằng cách gọi setFirstName: và sau đó gọi setLastName:. Trong khi đó, chuỗi B có thể gọi fullName ở giữa hai cuộc gọi của A và sẽ nhận được tên mới cùng với họ cũ.

Để giải quyết vấn đề này, bạn cần mô hình giao dịch. I E. một số loại đồng bộ hóa và / hoặc loại trừ khác cho phép một loại trừ quyền truy cập vào fullName trong khi các thuộc tính phụ thuộc đang được cập nhật.


1668
2018-02-26 06:40



Cho rằng bất kỳ mã an toàn thread nào cũng sẽ thực hiện khóa riêng của nó, khi nào bạn muốn sử dụng các trình truy cập thuộc tính nguyên tử? Tôi đang gặp rắc rối khi nghĩ đến một ví dụ điển hình. - Daniel Dickison
@bbum Làm cho tinh thần. Tôi thích bình luận của bạn cho câu trả lời khác rằng an toàn luồng là một mối quan tâm ở mức mô hình. Từ định nghĩa an toàn chủ đề của IBM: ibm.co/yTEbjY "Nếu một lớp được triển khai đúng, đó là một cách khác để nói rằng nó phù hợp với đặc điểm kỹ thuật của nó, không có chuỗi các hoạt động (đọc hoặc viết các trường công khai và các cuộc gọi đến các phương thức công khai) trên các đối tượng của lớp đó sẽ có thể đặt đối tượng vào trạng thái không hợp lệ, quan sát đối tượng ở trạng thái không hợp lệ hoặc vi phạm bất kỳ biến thể, điều kiện tiên quyết hoặc postconditions nào của lớp. " - Ben Flynn
Đây là một ví dụ tương tự như của @StevenKramer: Tôi có một @property NSArray* astronomicalEvents; liệt kê dữ liệu tôi muốn hiển thị trong giao diện người dùng. Khi ứng dụng khởi chạy con trỏ trỏ đến một mảng trống, thì ứng dụng sẽ lấy dữ liệu từ web. Khi yêu cầu web hoàn thành (trong một chủ đề khác nhau), ứng dụng sẽ tạo một mảng mới, sau đó đặt thuộc tính nguyên tử thành giá trị con trỏ mới. Đó là chủ đề an toàn và tôi không phải viết bất kỳ mã khóa nào, trừ khi tôi thiếu một thứ gì đó. Có vẻ khá hữu ích với tôi. - bugloaf
@HotLicks Một thú vị khác; trên một số kiến ​​trúc nhất định (Không thể nhớ cái nào), các giá trị 64 bit được truyền dưới dạng đối số có thể được chuyển một nửa trong sổ đăng ký và một nửa trên ngăn xếp. atomic ngăn chặn đọc một nửa giá trị của chủ đề chéo. (Đó là một lỗi thú vị để theo dõi.) - bbum
@congliu Thread A trả về một đối tượng mà không có retain/autorelease nhảy. Chủ đề B giải phóng đối tượng. Chủ đề A đi sự bùng nổ. atomic đảm bảo rằng luồng A có tham chiếu mạnh (số lần giữ lại +1) cho giá trị trả lại. - bbum


Điều này được giải thích trong Apple tài liệu, nhưng dưới đây là một số ví dụ về những gì đang thực sự xảy ra. Lưu ý rằng không có từ khóa "nguyên tử", nếu bạn không chỉ định "nonatomic" thì thuộc tính là nguyên tử, nhưng chỉ định "nguyên tử" một cách rõ ràng sẽ dẫn đến lỗi.

//@property(nonatomic, retain) UITextField *userName;
//Generates roughly

- (UITextField *) userName {
    return userName;
}

- (void) setUserName:(UITextField *)userName_ {
    [userName_ retain];
    [userName release];
    userName = userName_;
}

Bây giờ, biến thể nguyên tử phức tạp hơn một chút:

//@property(retain) UITextField *userName;
//Generates roughly

- (UITextField *) userName {
    UITextField *retval = nil;
    @synchronized(self) {
        retval = [[userName retain] autorelease];
    }
    return retval;
}

- (void) setUserName:(UITextField *)userName_ {
    @synchronized(self) {
      [userName_ retain];
      [userName release];
      userName = userName_;
    }
}

Về cơ bản, phiên bản nguyên tử phải lấy một khóa để đảm bảo an toàn luồng, và cũng đang tăng số lượng ref trên đối tượng (và số đếm autorelease để cân bằng nó) để đối tượng được đảm bảo tồn tại cho người gọi, nếu không có là một điều kiện chạy tiềm năng nếu một luồng khác đang thiết lập giá trị, làm cho số đếm ref giảm xuống 0.

Thực tế có một số lượng lớn các biến thể khác nhau về cách những thứ này hoạt động phụ thuộc vào việc các thuộc tính là các giá trị vô hướng hay các đối tượng và cách giữ lại, sao chép, chỉ đọc, nonatomic, vv tương tác. Nói chung, các bộ tổng hợp thuộc tính chỉ biết cách thực hiện "điều đúng" cho tất cả các kết hợp.


342
2018-02-26 06:24



Không phải là khóa không "đảm bảo an toàn luồng". - Jonathan Sterling
@Louis Gerbarg: Tôi tin rằng phiên bản của bạn của (nonatomic, giữ lại) setter sẽ không hoạt động đúng nếu bạn cố gắng chỉ định cùng một đối tượng (đó là: userName == userName_) - Florin
Mã của bạn hơi gây nhầm lẫn; có Không đảm bảo về những gì getters / setters nguyên tử được đồng bộ hóa. Nghiêm túc,@property (assign) id delegate; không được đồng bộ hóa trên bất kỳ thứ gì (iOS SDK GCC 4.2 ARM -Os), có nghĩa là có một cuộc đua giữa [self.delegate delegateMethod:self]; và foo.delegate = nil; self.foo = nil; [super dealloc];. Xem stackoverflow.com/questions/917884/… - tc.
@fyolnish Tôi không chắc chắn những gì _val/val là, nhưng không, không thực sự. Các getter cho một nguyên tử copy/retain tài sản cần đảm bảo rằng nó không trả về một đối tượng có refcount trở thành zero do setter được gọi trong thread khác, về cơ bản có nghĩa là nó cần đọc ivar, giữ lại nó trong khi đảm bảo rằng setter đã không ghi đè và phát hành nó , và sau đó autorelease nó để cân bằng giữ lại. Điều đó có nghĩa là cả hai getter và setter phải sử dụng một khóa (nếu bố trí bộ nhớ đã được sửa, nó có thể thực hiện được với các lệnh CAS2; -retain là một cuộc gọi phương thức). - tc.
@tc Đã khá lâu rồi nhưng những gì tôi muốn viết có lẽ là: gist.github.com/fjolnir/5d96b3272c6255f6baae Nhưng có, nó có thể cho giá trị cũ được đọc bởi một người đọc trước khi setFoo: trả về, và phát hành trước khi người đọc trả về nó. Nhưng có lẽ nếu setter sử dụng -autorelease thay vì-release, điều đó sẽ khắc phục điều đó. - Fjölnir


Nguyên tử

  • là hành vi mặc định
  • sẽ đảm bảo quá trình hiện tại được hoàn thành bởi CPU, trước khi một quá trình khác truy cập biến
  • không nhanh, vì nó đảm bảo quá trình được hoàn thành hoàn toàn

Không nguyên tử

  • KHÔNG phải là hành vi mặc định
  • nhanh hơn (đối với mã được tổng hợp, tức là, đối với các biến được tạo bằng cách sử dụng @property và @synthesize)
  • không an toàn chỉ
  • có thể dẫn đến hành vi bất ngờ, khi hai quá trình khác nhau truy cập cùng một biến cùng một lúc

148
2018-05-25 10:56





Cách tốt nhất để hiểu sự khác biệt là sử dụng ví dụ sau.

Giả sử có một thuộc tính chuỗi nguyên tử được gọi là "tên" và nếu bạn gọi [self setName:@"A"] từ chuỗi A, gọi [self setName:@"B"] từ chuỗi B và gọi [self name] từ chuỗi C, sau đó tất cả các hoạt động trên các luồng khác nhau sẽ được thực hiện theo kiểu serially, nghĩa là nếu một luồng đang thực hiện một bộ setter hoặc getter, thì các luồng khác sẽ đợi.

Điều này làm cho thuộc tính "tên" đọc / ghi an toàn, nhưng nếu một luồng khác, D, các cuộc gọi [name release] đồng thời, thao tác này có thể gây ra sự cố do không có lệnh gọi setter / getter nào tham gia ở đây. Điều này có nghĩa là một đối tượng đọc / ghi an toàn (ATOMIC), nhưng không an toàn với luồng như một luồng khác có thể đồng thời gửi bất kỳ loại thông điệp nào đến đối tượng. Nhà phát triển phải đảm bảo an toàn luồng cho các đối tượng đó.

Nếu thuộc tính "name" là nonatomic, thì tất cả các luồng trong ví dụ trên - A, B, C và D sẽ thực hiện đồng thời tạo ra bất kỳ kết quả không thể đoán trước nào. Trong trường hợp nguyên tử, một trong hai A, B hoặc C sẽ thực thi trước, nhưng D vẫn có thể thực hiện song song.


125
2018-01-31 18:36





Cú pháp và ngữ nghĩa đã được xác định rõ bởi các câu trả lời xuất sắc khác cho câu hỏi này. Bởi vì chấp hành và hiệu suất không chi tiết tốt, tôi sẽ thêm câu trả lời của tôi.

Sự khác nhau chức năng giữa 3 là gì?

Tôi luôn coi nguyên tử là một mặc định khá tò mò. Ở cấp độ trừu tượng, chúng tôi làm việc tại, sử dụng các thuộc tính nguyên tử cho một lớp học như một phương tiện để đạt được 100% an toàn chỉ là một trường hợp góc. Đối với các chương trình đa luồng thực sự chính xác, sự can thiệp của lập trình viên gần như chắc chắn là một yêu cầu. Trong khi đó, đặc tính hiệu suất và thực hiện chưa được chi tiết theo chiều sâu. Đã viết một số chương trình đa luồng nặng nề trong những năm qua, tôi đã tuyên bố tài sản của mình là nonatomictoàn bộ thời gian vì nguyên tử không hợp lý cho bất kỳ mục đích nào. Trong khi thảo luận về các chi tiết của các thuộc tính nguyên tử và phi nguyên tử câu hỏi này, Tôi đã làm một số hồ sơ gặp phải một số kết quả tò mò.

Chấp hành

Được. Điều đầu tiên tôi muốn làm rõ là việc triển khai khóa được thực hiện xác định và trừu tượng hóa. Louis sử dụng @synchronized(self) trong ví dụ của ông - tôi đã thấy điều này như một nguồn gây nhầm lẫn chung. Việc triển khai không thực ra sử dụng @synchronized(self); nó sử dụng mức đối tượng spin ổ khóa. Minh họa của Louis là tốt cho một minh họa cao cấp bằng cách sử dụng các cấu trúc chúng ta đều quen thuộc với, nhưng điều quan trọng là phải biết nó không sử dụng @synchronized(self).

Một sự khác biệt khác là các thuộc tính nguyên tử sẽ giữ lại / giải phóng chu kỳ các đối tượng của bạn bên trong getter.

Hiệu suất

Đây là phần thú vị: Hiệu suất sử dụng truy cập thuộc tính nguyên tử trong không bị quấy rầy (ví dụ: các trường hợp một luồng) có thể thực sự rất nhanh trong một số trường hợp. Trong trường hợp ít hơn lý tưởng, việc sử dụng các truy cập nguyên tử có thể tốn hơn 20 lần chi phí của nonatomic. Trong khi Đã tranh cãi trường hợp sử dụng 7 luồng chậm hơn 44 lần đối với cấu trúc ba byte (2,2 GHz Core i7 Quad Core, x86_64). Cấu trúc ba byte là một ví dụ về thuộc tính rất chậm.

Lưu ý thú vị: Người truy cập xác định người truy cập của cấu trúc ba byte nhanh gấp 52 lần so với những người truy cập nguyên tử tổng hợp; hoặc 84% tốc độ của các bộ tiếp cận phi y tế tổng hợp.

Các đối tượng trong các trường hợp tranh chấp cũng có thể vượt quá 50 lần.

Do số lượng tối ưu hóa và các biến thể trong việc triển khai, việc đo lường các tác động trong thế giới thực trong các ngữ cảnh này là khá khó khăn. Bạn thường có thể nghe thấy một cái gì đó như "Tin tưởng nó, trừ khi bạn hồ sơ và tìm thấy nó là một vấn đề". Do mức độ trừu tượng, nó thực sự khá khó khăn để đo lường tác động thực tế. Việc thu thập chi phí thực tế từ các hồ sơ có thể rất tốn thời gian, và do trừu tượng hóa, khá không chính xác. Đồng thời, ARC và MRC có thể tạo ra sự khác biệt lớn.

Hãy quay lại, không phải tập trung vào việc thực hiện quyền truy cập thuộc tính, chúng tôi sẽ bao gồm các nghi phạm thông thường như objc_msgSendvà kiểm tra một số kết quả cấp cao trong thế giới thực cho nhiều cuộc gọi đến NSString getter in không bị quấy rầy trường hợp (giá trị tính bằng giây):

  • MRC | nonatomic | getters được thực hiện thủ công: 2
  • MRC | nonatomic | tổng hợp getter: 7
  • MRC | nguyên tử | tổng hợp getter: 47
  • ARC | nonatomic | tổng hợp getter: 38 (lưu ý: ARC thêm ref count đạp ở đây)
  • ARC | nguyên tử | tổng hợp getter: 47

Như bạn có thể đoán, tham số đếm hoạt động / đi xe đạp là một đóng góp đáng kể với nguyên tử và dưới ARC. Bạn cũng sẽ thấy sự khác biệt lớn hơn trong các trường hợp tranh chấp.

Mặc dù tôi chú ý đến hiệu suất, tôi vẫn nói Ngữ nghĩa đầu tiên!. Trong khi đó, hiệu suất là ưu tiên thấp đối với nhiều dự án. Tuy nhiên, biết chi tiết thực hiện và chi phí của công nghệ bạn sử dụng chắc chắn không làm tổn thương. Bạn nên sử dụng công nghệ phù hợp với nhu cầu, mục đích và khả năng của mình. Hy vọng rằng điều này sẽ giúp bạn tiết kiệm một vài giờ so sánh, và giúp bạn đưa ra quyết định sáng suốt hơn khi thiết kế các chương trình của bạn.


108
2017-08-18 09:47



MRC | nguyên tử | tổng hợp getter: 47 ARC | nguyên tử | tổng hợp getter: 47 Điều gì làm cho chúng giống nhau? Không nên ARC có nhiều chi phí hơn? - SDEZero
Vì vậy, nếu các thuộc tính nguyên tử là xấu y thì chúng là mặc định. Để tăng mã boilerplate? - Kunal Balani
@ LearnCocos2D tôi vừa thử nghiệm trên 10.8.5 trên cùng một máy, nhắm mục tiêu 10.8, cho trường hợp không được phân luồng đơn luồng với một NSString đó không phải là bất tử: -ARC atomic (BASELINE): 100% -ARC nonatomic, synthesised: 94% -ARC nonatomic, user defined: 86% -MRC nonatomic, user defined: 5% -MRC nonatomic, synthesised: 19% -MRC atomic: 102% - kết quả có một chút khác biệt ngày hôm nay. Tôi đã không làm bất kỳ @synchronizedso sánh. @synchronized có ngữ nghĩa khác nhau, và tôi không coi đó là một công cụ tốt nếu bạn có các chương trình đồng thời nontrivial. nếu bạn cần tốc độ, tránh @synchronized. - justin
bạn có thử nghiệm trực tuyến ở đâu đó không? Tôi tiếp tục bổ sung thêm của tôi ở đây: github.com/LearnCocos2D/LearnCocos2D/tree/master/… - LearnCocos2D
@ LearnCocos2D tôi đã không chuẩn bị chúng cho tiêu dùng của con người, xin lỗi. - justin


Nguyên tử= chủ đề an toàn

Không nguyên tử = Không có chủ đề an toàn

An toàn chủ đề:

Các biến cá thể là an toàn luồng nếu chúng hoạt động chính xác khi được truy cập từ nhiều luồng, bất kể lập lịch hay xen kẽ việc thực hiện các luồng đó theo môi trường thời gian chạy và không có đồng bộ hóa bổ sung hoặc phối hợp khác trên một phần của mã gọi.

Trong bối cảnh của chúng tôi:

Nếu một chuỗi thay đổi giá trị của cá thể thì giá trị đã thay đổi có sẵn cho tất cả các chuỗi và chỉ một chuỗi có thể thay đổi giá trị tại một thời điểm.

Sử dụng ở đâu atomic:

nếu biến cá thể sẽ được truy cập trong môi trường đa luồng.

Ngụ ý của atomic:

Không nhanh như nonatomic bởi vì nonatomic không yêu cầu bất kỳ cơ quan giám sát nào hoạt động trên đó từ thời gian chạy.

Sử dụng ở đâu nonatomic:

Nếu biến cá thể sẽ không bị thay đổi bởi nhiều luồng, bạn có thể sử dụng nó. Nó cải thiện hiệu suất.


89
2017-07-10 13:07



Tất cả mọi thứ bạn nói ở đây là chính xác, nhưng câu cuối cùng về cơ bản là "sai", Dura, cho lập trình ngày nay. Nó thực sự không thể tưởng tượng bạn sẽ bận tâm để cố gắng "cải thiện hiệu suất" theo cách này. (Ý tôi là, trước khi bạn hiểu được điều đó, bạn sẽ "không sử dụng ARC", "không sử dụng NSString vì nó chậm!"). Để làm một ví dụ cực đoan, nó sẽ giống như là "đội, không đặt bất kỳ nhận xét nào trong mã, vì nó làm chậm chúng tôi. " Không có đường ống phát triển thực tế, nơi bạn sẽ muốn (không tồn tại) hiệu suất lý thuyết đạt được vì lợi ích của không đáng tin cậy. - Fattie
@ JoeBlow một thực tế của nó, bạn có thể xác minh nó ở đây developer.apple.com/library/mac/documentation/Cocoa/Conceptual/… - Durai Amuthan.H
Giải thích tốt nhất (y) - Sunil Targe


Tôi tìm thấy một giải thích khá tốt về các thuộc tính nguyên tử và phi nguyên tử đây. Dưới đây là một số văn bản có liên quan giống nhau:

'nguyên tử' có nghĩa là nó không thể bị phá vỡ.   Trong thuật ngữ OS / lập trình, một cuộc gọi hàm nguyên tử là một hàm không thể bị gián đoạn - toàn bộ chức năng phải được thực thi và không được hoán đổi ra khỏi CPU bằng cách chuyển ngữ cảnh thông thường của hệ điều hành cho đến khi hoàn thành. Chỉ trong trường hợp bạn không biết: vì CPU chỉ có thể thực hiện một việc tại một thời điểm, hệ điều hành quay quyền truy cập vào CPU cho tất cả các quy trình đang chạy trong các lát thời gian nhỏ, để cung cấp cho ảo giác của đa nhiệm. Bộ lập lịch CPU có thể (và không) làm gián đoạn quá trình tại bất kỳ điểm nào trong quá trình thực hiện của nó - ngay cả trong cuộc gọi hàm trung bình. Vì vậy, đối với các hành động như cập nhật biến truy cập được chia sẻ trong đó hai quy trình có thể cố gắng cập nhật biến cùng một lúc, chúng phải được thực thi 'nguyên tử', tức là mỗi hành động cập nhật phải hoàn thành toàn bộ trước khi bất kỳ quá trình nào khác có thể được hoán đổi lên CPU.

Vì vậy, tôi sẽ đoán rằng nguyên tử trong trường hợp này có nghĩa là các phương thức đọc thuộc tính không thể bị gián đoạn - có nghĩa là các biến được đọc bởi phương thức không thể thay đổi giá trị của chúng một nửa bởi vì một số thread / call / function khác trao đổi trên CPU.

Bởi vì atomic các biến không thể bị gián đoạn, giá trị mà chúng chứa ở bất kỳ điểm nào là (thread-lock) được bảo đảm là không lo lắng, mặc dù, đảm bảo khóa luồng này giúp truy cập chúng chậm hơn. non-atomic biến, mặt khác, không đảm bảo như vậy nhưng làm cho sự sang trọng của truy cập nhanh hơn. Tóm lại, đi với non-atomic khi bạn biết các biến của bạn sẽ không được truy cập bởi nhiều chủ đề cùng một lúc và tăng tốc độ.


67
2018-02-24 05:17





Sau khi đọc rất nhiều bài viết, các bài viết Stack Overflow và tạo các ứng dụng demo để kiểm tra các thuộc tính thuộc tính biến, tôi quyết định đặt tất cả các thông tin thuộc tính với nhau:

  1. atomic             // Mặc định
  2. nonatomic
  3. strong = retain        // Mặc định
  4. weak = unsafe_unretained
  5. retain
  6. assign             // Mặc định
  7. unsafe_unretained
  8. copy
  9. readonly
  10. readwrite                 // Mặc định

Trong bài viết Thuộc tính thuộc tính biến hoặc công cụ sửa đổi trong iOS bạn có thể tìm thấy tất cả các thuộc tính nêu trên và điều đó chắc chắn sẽ giúp bạn.

  1. atomic

    • atomic có nghĩa là chỉ có một luồng truy cập biến (kiểu tĩnh).
    • atomic là chủ đề an toàn.
    • Nhưng nó hoạt động chậm
    • atomic là hành vi mặc định
    • Truy cập nguyên tử trong môi trường không thu gom rác (tức là khi sử dụng lưu giữ / giải phóng / tự động phát) sẽ sử dụng khóa để đảm bảo rằng một chuỗi khác không ảnh hưởng đến cài đặt / nhận giá trị chính xác.
    • Nó không thực sự là một từ khóa.
       

    Thí dụ:

        @property (retain) NSString *name;
    
        @synthesize name;
    
  2. nonatomic

    • nonatomic có nghĩa là nhiều chuỗi truy cập biến (loại động).
    • nonatomic không an toàn.
    • Nhưng nó hoạt động nhanh
    • nonatomic KHÔNG phải là hành vi mặc định. Chúng ta cần thêm nonatomic từ khóa trong thuộc tính thuộc tính.
    • Nó có thể dẫn đến hành vi bất ngờ, khi hai quá trình (luồng) khác nhau truy cập cùng một biến cùng một lúc.
       

    Thí dụ:

        @property (nonatomic, retain) NSString *name;
    
        @synthesize name;
    

61
2018-03-21 07:10



Làm thế nào có thể gán và mạnh / giữ lại cả hai được mặc định? - BangOperator
mạnh mẽ đi kèm với ARC, giữ lại là mặc định trước ARC - abdullahselek


Câu trả lời dễ nhất trước tiên: Không có sự khác biệt giữa hai ví dụ thứ hai của bạn. Theo mặc định, các trình truy cập thuộc tính là nguyên tử.

Truy cập nguyên tử trong môi trường không thu gom rác (tức là khi sử dụng lưu giữ / giải phóng / tự động phát) sẽ sử dụng khóa để đảm bảo rằng một chuỗi khác không ảnh hưởng đến cài đặt / nhận giá trị chính xác.

Xem "Hiệu suất và luồng"phần tài liệu hướng đối tượng-C 2.0 của Apple để biết thêm thông tin và các cân nhắc khác khi tạo ứng dụng đa luồng.


52
2018-02-26 02:56



Hai lý do. Đầu tiên, cho mã tổng hợp nó tạo ra nhanh hơn (nhưng không phải mã luồng an toàn). Thứ hai, nếu bạn đang viết các trình khách truy cập không phải là nguyên tử, nó cho phép bạn chú thích cho bất kỳ người dùng nào trong tương lai rằng mã không phải là nguyên tử khi họ đọc giao diện của nó, mà không làm cho chúng thực hiện. - Louis Gerbarg
@ Dogweather: xem Tại sao các thuộc tính IBOutlet của Cocoa lại mặc định là nguyên tử, và Cocoa Touch thì không? - Anoop Vaidya


Nguyên tử:

Đảm bảo nguyên tử rằng quyền truy cập vào thuộc tính sẽ được thực hiện theo cách nguyên tử. Ví dụ. nó luôn trả về một đối tượng khởi tạo hoàn toàn, bất kỳ get / set của một thuộc tính nào trên một luồng phải hoàn thành trước khi một đối tượng khác có thể truy cập nó.

Nếu bạn tưởng tượng hàm sau xuất hiện trên hai luồng cùng một lúc, bạn có thể thấy tại sao kết quả không đẹp.

-(void) setName:(NSString*)string
{
  if (name)
  {
    [name release]; 
    // what happens if the second thread jumps in now !?
    // name may be deleted, but our 'name' variable is still set!
    name = nil;
  }

  ...
}

Ưu điểm: Trả lại các đối tượng được khởi tạo hoàn toàn mỗi lần làm cho nó trở thành lựa chọn tốt nhất trong trường hợp đa luồng.

Nhược điểm: Hiệu suất đạt được, giúp thực hiện chậm hơn một chút

Không phải nguyên tử:

Không giống như Atomic, nó không đảm bảo đối tượng khởi tạo hoàn toàn trả về mỗi lần.

Ưu điểm: Thực hiện cực nhanh.

Nhược điểm: Có thể có giá trị rác trong trường hợp đa luồng.


52
2018-02-26 02:41



Nhận xét đó không có ý nghĩa gì nhiều. Bạn có thể làm rõ? Nếu bạn nhìn vào các ví dụ trên trang web của Apple thì từ khóa nguyên tử đồng bộ hóa trên đối tượng trong khi cập nhật các thuộc tính của nó. - Andrew Grant
Câu trả lời này có ý nghĩa hơn với tôi sau đó bất kỳ câu trả lời nào khác bằng cách nào đó! Cảm ơn lời giải thích. - dreamBegin