@synchronizedディレクティブがどのように機能するかを確認するために、このマルチスレッドアプリケーションを実行しています。すべてのスレッドが@synchronizedの引数と同じオブジェクトを持っている場合、それらはすべて同じロックで待機することを読みました。すべてのスレッドで同じであるため、引数として。
このアプリケーションでは、すべてのスレッドによって複数回編集されているテキストフィールドがあります。パフォーマンスは気にしません。これは単なるテストなので、@ synchronizedディレクティブをforの前ではなく、その中に入れます。
私が使用するプロパティ:
@property (weak) IBOutlet NSTextField *textField;
@property (nonatomic, copy) NSNumber* value;
@property (nonatomic,copy) NSMutableArray* threads;
コード:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
value= @0;
textField.objectValue= value;
for(int i=0; i<10; i++)
{
NSThread* thread=[[NSThread alloc]initWithTarget: self selector: @selector(routine:) object: nil];
[threads addObject: thread];
[thread start];
}
}
- (void) routine : (id) argument
{
for(NSUInteger i=0; i<100; i++)
{
@synchronized(self)
{
value= @(value.intValue+1);
textField.objectValue= value;
}
}
}
アプリケーションが成功し、テキストフィールドの値として1000が表示される場合もありますが、そうでない場合もありますが、これが飢餓であり、テキストフィールドに何も表示されず、空です。デバッグを試しましたが、何が表示されているのかわかりません。間違っています。失敗の基準は私にはさりげなく思えるので、うまくいくこともあります。
解決
@synthesize threads,value, textField;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
value= @0;
threads=[[NSMutableArray alloc]initWithCapacity: 100];
for(NSUInteger i=0; i<100; i++)
{
NSThread* thread=[[NSThread alloc]initWithTarget: self selector: @selector(routine:) object: nil ];
[threads addObject: thread];
[thread start];
}
}
- (void) routine : (id) arg
{
for(NSUInteger i=0; i<1000; i++)
{
@synchronized(self)
{
value= @(value.intValue+1);
[textField performSelectorOnMainThread: @selector(setObjectValue:) withObject: value waitUntilDone: NO];
}
}
}