iOSでのロックメカニズム

3567 ワード

本論文では,OCにおける種々のロックの使用について主に論じた.まず、テスト用のクラスを作成します.このテストクラスが共有リソースであり、method 1とmethod 2が反発すると仮定します.テストクラス:


#import "TestObject.h"

@implementation TestObject

- (void)method1
{
    NSLog(@"%@",NSStringFromSelector(_cmd));
}

- (void)method2
{
    NSLog(@"%@",NSStringFromSelector(_cmd));
}

@end


1.NSLockによるロック
TestObject *obj = [[TestObject alloc] init];
NSLock *lock = [[NSLock alloc] init];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [lock lock];
    [obj method1];
    sleep(10);
    [lock unlock];
});

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    sleep(1);// 2 
    [lock lock];
    [obj method2];
    [lock unlock];
});

NSLockは、lockメソッドとunlockメソッドに加えて、tryLocklockBeforeDateの2つのメソッドを提供しています.前のメソッドは、ロックが使用できない場合(ロックされている場合)、スレッドをブロックせずにNOを返します.lockBeforeDate:メソッドは、指定したDateの前にロックを試み、指定した時間までにロックができない場合はNOを返します.
2.synchronizedキーワードを使用して構築されたロック

TestObject *obj = [[TestObject alloc] init];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    @synchronized(obj){
        [obj method1];
        sleep(10);
    }
});

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    sleep(1);
    @synchronized(obj){
        [obj method2];
    }
});


@synchronized命令で使用されるobjは、このロックの一意の識別であり、識別が同じである場合にのみ反発を満たすために、スレッド2の@synchronized(obj)@synchronized(other)に変更されると、剛スレッド2がブロックされないため、@synchronized命令がロックを実現する利点は、コードに明示的に を作成する必要がなく、ロックのメカニズムを実現することができるが、予防措置として、@synchronizedブロックは、異常放出時に自動的に反発ロックを解放する異常処理ルーチンを暗黙的に追加してコードを保護します.したがって、暗黙的な例外処理ルーチンに追加のオーバーヘッドをもたらしたくない場合は、ロックオブジェクトの使用を考慮することができます.
3.C言語を使用したpthread_mutex_t実装のロック


TestObject *obj = [[TestObject alloc] init];

__block pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    pthread_mutex_lock(&mutex);
    [obj method1];
    sleep(5);
    pthread_mutex_unlock(&mutex);
});

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    sleep(1);
    pthread_mutex_lock(&mutex);
    [obj method2];
    pthread_mutex_unlock(&mutex);
});


pthread_mutex_tはC言語のpthread.hに定義されているので、インポートヘッダファイルは#includeを使用します.
4.GCDで実現した「ロック」
以上のコードでマルチスレッドを構築するには、GCDのdispatch_asyncの方法が使用されていますが、実際にはGCDにも が提供されています.これを使用して、「ロック」(本質的には、 は違いがあります.具体的な違いは、信号量と反発ロックの違いを自行で確認してください)

TestObject *obj = [[TestObject alloc] init];
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    [obj method1];
    sleep(10);
    dispatch_semaphore_signal(semaphore);
});

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    sleep(1);
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    [obj method2];
    dispatch_semaphore_signal(semaphore);
});


以上が一般的なロックメカニズムであり、ネット上で資料を調べるとOSSpinLockのスピンロック効率が最も高いと言われていますが、現在は多くの人がスピンロックが安全ではないと言っています.OSSpinLockを含めると、各種ロックの効率は以下の通りです.
OSSpinLock > pthread_mutex > NSLock > semaphore > @Sych

OSSpinLockが安全かどうかの問題があれば、すぐに更新します.