What advantage(s) does dispatch_sync have over @synchronized?

前端 未结 4 1441
萌比男神i
萌比男神i 2020-12-02 08:22

Lets say I want to make this code thread-safe:

- (void) addThing:(id)thing { // Can be called from different threads
    [_myArray addObject:thing];
}
         


        
4条回答
  •  情书的邮戳
    2020-12-02 08:28

    Ok, I done some more tests and here are results:

    lock test: mean:2.48661, stdDev:0.50599

    synchronized test: mean:2.51298, stdDev:0.49814

    dispatch Test: mean:2.17046, stdDev:0.43199

    So I was wrong, my bad :( If somebody is interested in test code it's avail here:

    static NSInteger retCount = 0;
    
    @interface testObj : NSObject
    @end
    
    @implementation testObj
    
    -(id)retain{
        retCount++;
        return [super retain];
    }
    @end
    
    @interface ViewController : UIViewController{
        NSMutableArray* _a;
        NSInteger _c;
        NSLock* lock;
        NSLock* thlock;
        dispatch_queue_t _q;
    }
    
    - (IBAction)testBtn:(id)sender;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    }
    
    -(NSTimeInterval)testCase:(SEL)aSel name:(NSString*)name{
        _a = [[NSMutableArray alloc] init];
        retCount = 0;
        //Sync test
        NSThread* th[10];
        for(int t = 0; t < 10;t ++){
            th[t] = [[NSThread alloc] initWithTarget:self selector:aSel object:nil];
        }
    
        NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];
        for(int t = 0; t < 10;t ++){
            [th[t] start];
        }
        NSInteger thCount = 1;
        while(thCount > 0){
            thCount = 0;
            for(int t = 0; t < 10;t ++){
                thCount += [th[t] isFinished] ? 0 : 1;
            }
        }
        NSTimeInterval end = [NSDate timeIntervalSinceReferenceDate];
        NSLog(@"%@: %2.5f, retainCount:%d, _c:%d, objects:%d", name, end-start, retCount, _c, [_a count]);
        [_a release];
        for(int t = 0; t < 10;t ++){
            [th[t] release];
        }
        return end-start;
    }
    
    -(void)syncTest{
        for(int t = 0; t < 5000; t ++){
            [self synchronizedAdd:[[[testObj alloc] init] autorelease] ];
        }
    }
    
    -(void)dispTest{
        for(int t = 0; t < 5000; t ++){
            [self dispatchSyncAdd:[[[testObj alloc] init] autorelease] ];
        }
    }
    
    -(void)lockTest{
        for(int t = 0; t < 5000; t ++){
            [self lockAdd:[[[testObj alloc] init] autorelease] ];
        }
    }
    
    
    - (void) synchronizedAdd:(NSObject*)anObject
    {
        @synchronized(self) {
            [_a addObject:anObject];
            _c++;
        }
    }
    
    - (void) dispatchSyncAdd:(NSObject*)anObject
    {
        dispatch_sync(_q, ^{
            [_a addObject:anObject];
            _c++;
        });
    }
    
    - (void) lockAdd:(NSObject*)anObject
    {
        [lock lock];
            [_a addObject:anObject];
            _c++;
        [lock unlock];
    }
    
    - (double)meanOf:(NSArray *)array
    {
        double runningTotal = 0.0;
    
        for(NSNumber *number in array)
        {
            runningTotal += [number doubleValue];
        }
    
        return (runningTotal / [array count]);
    }
    
    - (double)standardDeviationOf:(NSArray *)array
    {
        if(![array count]) return 0;
    
        double mean = [self meanOf:array];
        double sumOfSquaredDifferences = 0.0;
    
        for(NSNumber *number in array)
        {
            double valueOfNumber = [number doubleValue];
            double difference = valueOfNumber - mean;
            sumOfSquaredDifferences += difference * difference;
        }
    
        return sqrt(sumOfSquaredDifferences / [array count]);
    }
    
    -(void)stats:(NSArray*)data name:(NSString*)name{
        NSLog(@"%@: mean:%2.5f, stdDev:%2.5f", name, [self meanOf:data], [self standardDeviationOf:data]);
    }
    
    - (IBAction)testBtn:(id)sender {
        _q = dispatch_queue_create("array q", DISPATCH_QUEUE_SERIAL);
        lock = [[NSLock alloc] init];
        NSMutableArray* ltd = [NSMutableArray array];
        NSMutableArray* std = [NSMutableArray array];
        NSMutableArray* dtd = [NSMutableArray array];
        for(int t = 0; t < 20; t++){
            [ltd addObject: @( [self testCase:@selector(lockTest) name:@"lock Test"] )];
            [std addObject: @( [self testCase:@selector(syncTest) name:@"synchronized Test"] )];
            [dtd addObject: @( [self testCase:@selector(dispTest) name:@"dispatch Test"] )];
        }
        [self stats: ltd name:@"lock test"];
        [self stats: std name:@"synchronized test"];
        [self stats: dtd name:@"dispatch Test"];
    }
    @end
    

提交回复
热议问题