关于 @synchronized
来源:互联网 发布:大疆视频剪辑软件 编辑:程序博客网 时间:2024/05/29 15:07
本文翻译自 Ryan Kaplan 的 More than you want to know about @synchronized
http://yulingtianxia.com/blog/2015/11/01/More-than-you-want-to-know-about-synchronized/?
因为原文一些内容写的不太准确,我按照我的理解做出了批注和补充。
如果你已经使用 Objective-C 编写过任何并发程序,那么想必是见过 @synchronized
这货了。@synchronized
结构所做的事情跟锁(lock)类似:它防止不同的线程同时执行同一段代码。但在某些情况下,相比于使用 NSLock
创建锁对象、加锁和解锁来说,@synchronized
用着更方便,可读性更高。
译者注:这与苹果官方文档对
@synchronized
的介绍有少许出入,但意思差不多。苹果官方文档更强调它“防止不同的线程同时获取相同的锁”,因为文档在集中介绍多线程编程各种锁的作用,所以更强调“相同的锁”而不是“同一段代码”。
如果你之前没用过 @synchronized
,接下来有个使用它的例子。这篇文章实质上是谈谈有关我对 @synchronized
实现原理的一个简短研究。
用到 @synchronized 的例子
假设我们正在用 Objective-C 实现一个线程安全的队列,我们一开始可能会这么干:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@implementation ThreadSafeQueue
{
NSMutableArray *_elements;
NSLock *_lock;
}
- (instancetype)init
{
self = [super init];
if (self) {
_elements = [NSMutableArray array];
_lock = [[NSLock alloc] init];
}
return self;
}
- (void)push:(id)element
{
[_lock lock];
[_elements addObject:element];
[_lock unlock];
}
@end
上面的 ThreadSafeQueue
类有个 init
方法,它初始化了一个 _elements
数组和一个 NSLock
实例。这个类还有个 push:
方法,它先获取锁、然后向数组中插入元素、最终释放锁。可能会有许多线程同时调用 push:
方法,但是 [_elements addObject:element]
这行代码在任何时候将只会在一个线程上运行。步骤如下:
- 线程 A 调用
push:
方法 - 线程 B 调用
push:
方法 - 线程 B 调用
[_lock lock]
- 因为当前没有其他线程持有锁,线程 B 获得了锁 - 线程 A 调用
[_lock lock]
,但是锁已经被线程 B 占了所以方法调用并没有返回-这会暂停线程 A 的执行 - 线程 B 向
_elements
添加元素后调用[_lock unlock]
。当这些发生时,线程 A 的[_lock lock]
方法返回,并继续将自己的元素插入_elements
。
我们可以用 @synchronized
结构更简要地实现这些:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@implementation ThreadSafeQueue
{
NSMutableArray *_elements;
}
- (instancetype)init
{
self = [super init];
if (self) {
_elements = [NSMutableArray array];
}
return self;
}
- (void)increment
{
@synchronized (self) {
[_elements addObject:element];
}
}
@end
在前面的例子中,”synchronized block” 与 [_lock lock]
和 [_lock unlock]
效果相同。你可以把它当成是锁住self
,仿佛 self
就是个 NSLock
。锁在左括号 {
后面的任何代码运行之前被获取到,在右括号 }
后面的任何代码运行之前被释放掉。这爽就爽在妈妈再也不用担心我忘记调用 unlock
了!
你可以给任何 Objective-C 对象上加个 @synchronized
。那么我们也可以在上面的例子中用@synchronized(_elements)
来替代 @synchronized(self)
,效果是相同的。
回到研究上来
我对 @synchronized
的实现十分好奇并搜了一些它的细节。我找到了一些答案,但这些解释都没有达到我想要的深度。锁是如何与你传入 @synchronized
的对象关联上的?@synchronized
会保持(retain,增加引用计数)被锁住的对象么?假如你传入 @synchronized
的对象在 @synchronized
的 block 里面被释放或者被赋值为 nil
将会怎么样?这些全都是我想回答的问题。而我这次的收获,会要你好看
- 关于synchronized
- 关于synchronized
- 关于synchronized
- 关于synchronized
- 关于synchronized
- 关于synchronized
- 关于synchronized
- 关于synchronized
- 关于synchronized
- 关于synchronized
- 关于 @synchronized
- 关于synchronized
- 关于volatile和synchronized
- 关于synchronized(this)
- 关于 synchronized 的使用
- 关于volatile和synchronized
- 关于synchronized(this)
- 关于synchronized(obj)
- [扩展]EasyUI给dialog的buttons绑定click事件
- [c] 练习题
- Python中 L 的意思
- Python变量类型
- 如何分配变量到指定的地址
- 关于 @synchronized
- pop到指定页面
- viewcontroller页面间传值的几种方法
- C++动态链接库(DLL)编程深入浅出(zz)
- Android:Layout_weight的深刻理解
- 二叉树的递归遍历
- HashMap实现原理分析
- rpm 命令
- 三维重建: 点云三角化(二流型的)要点 —— 干货