现在的位置: 首页 > 综合 > 正文

iOS tips: @synchronized

2014年01月30日 ⁄ 综合 ⁄ 共 3584字 ⁄ 字号 评论关闭

转自:http://refactr.com/blog/2012/10/ios-tips-synchronized/

If you’re just getting started with threading in Objective-C, it won’t be long before you’ll need to make some thread-safe modifications to objects. One of the many useful tools that Objective-C gives us is the @synchronizeddirective.
From the documentation:

The @synchronized directive is a convenient way to create mutex locks on the fly in Objective-C code. The @synchronized directive does what any other mutex lock would do—it prevents different
threads from acquiring the same lock at the same time.

Using @synchronized is super easy

@synchronized(key) {
// thread-safe code goes here
}

Examples!

First we’re going to create an NSMutableArray and fill it with garbage.

bigArray = [NSMutableArray arrayWithCapacity:5];
 for (int i = 0; i < 5; i++) {
  [bigArray addObject:[NSString stringWithFormat:@"object-%i", i]];
}

And a method to display/modify the array.

- (void)updateBigArray:(NSString *)value {
 for (int j = 0; j < bigArray.count; j++) {
  NSString *currentObject = [bigArray objectAtIndex:j];

  [bigArray replaceObjectAtIndex:j withObject:[currentObject stringByAppendingFormat:@"-%@", value]];

  NSLog(@"%@", [bigArray objectAtIndex:j]);
 }
}

Now let’s call our method on two separate threads. Notice I’m sending foo in for both of them. I’ll explain why in a bit.

NSString *foo = @"foo";

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
 [self updateBigArray:foo];
});

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
 [self updateBigArray:foo];
});

This gives us the output:

object-0-foo
object-0-foo
object-1-foo-foo
object-1-foo
object-2-foo
object-2-foo
object-3-foo
object-3-foo
object-4-foo-foo
object-4-foo

Both threads are working over the top of each other which could lead to app crashes depending on what you’re doing. So let’s update our method to use@synchronized with value as our lock
key.

- (void)updateBigArray:(NSString *)value {
 @synchronized (value) {
  for (int j = 0; j < bigArray.count; j++) {
   NSString *currentObject = [bigArray objectAtIndex:j];

   [bigArray replaceObjectAtIndex:j withObject:[currentObject stringByAppendingFormat:@"-%@", value]];

   NSLog(@"%@", [bigArray objectAtIndex:j]);
  }
 }
}
object-0-foo
object-1-foo
object-2-foo
object-3-foo
object-4-foo
object-0-foo-foo
object-1-foo-foo
object-2-foo-foo
object-3-foo-foo
object-4-foo-foo

That looks a lot better. What’s happening is that our @synchronized block effectively pauses one thread, allowing the other thread access to the block, then un-pauses it once the first has finished.

So what about the key?

This is where it gets interesting. If you pass the same object to@synchronized as the key, it will get paused (which we just saw). However, if you send a different object than the key it will get through.
Remember when we passed foo through twice? Let’s pass something else the second time instead.

NSString *foo = @"foo";
NSString *bar = @"bar";

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
 [self updateBigArray:foo];
});

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
 [self updateBigArray:bar];
});
object-0-foo
object-0-bar
object-1-foo
object-1-bar
object-2-foo
object-2-foo-bar
object-3-foo
object-3-foo-bar
object-4-foo
object-4-foo-bar

There could be reasons why you would want to lock on value, but in this case it would be smarter to use a different key.
Let’s use

 @synchronized (bigArray) {
...

instead of

 @synchronized (value) {
...

object-0-foo
object-1-foo
object-2-foo
object-3-foo
object-4-foo
object-0-foo-bar
object-1-foo-bar
object-2-foo-bar
object-3-foo-bar
object-4-foo-bar

In the end

@synchronized is a great shorthand mutex lock. It may not be the most efficient lock, but chances are you won’t notice. If you’re just getting started with threading, I highly recommend getting more
familiar with it.

 

This entry was posted in Software Development and tagged .
Bookmark the permalink.

抱歉!评论已关闭.