利用ARC解决遗忘unlock的毛病
我们在使用lock的时候会有这样的情况:因为某方法内部逻辑较为复杂,会有很多地方return,稍不留神都会漏掉一次unlock的操作,在查看一些C++源码时发现一种比较优雅的设计,在某个方法或一个代码块需要锁时,不直接对锁进行操作,而是通过创建一个局部对象来管理这个锁,我们将这个对象称之为”哨兵”,该对象在构造函数中执行lock操作,而在析构函数中执行unlock,这样当我们需要加锁时只需要创建这个对象,当函数return后或代码块结束时,因为局部对象在超出作用域后释放,便自动完成了unlock的动作。
而在Objective-C中我们不能创建局部对象,但利用ARC的特性却也可以达到超出作用域自动释放的特性。
以下是”哨兵”类的实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
@
interface
QMGuard
:
NSObject
{
id
<
NSLocking
>
lock
;
}
@
end
@
implementation
QMGuard
-
(
id
)
initWithLock
:
(
id
<
NSLocking
>
)
obj
{
self
=
[
super
init
]
;
if
(
self
)
{
lock
=
obj
;
[
lock
lock
]
;
}
return
self
;
}
-
(
void
)
dealloc
{
[
lock
unlock
]
;
}
@
end
|
以下是我们在使用锁的时候:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
//为了方便使用
#define QUARD(lock) \
QMGuard *
_guard_
=
[
[
QMGuard
alloc
]
initWithLock
:
lock
]
;
\
NSAssert
(
_guard_
,
@
"_guard_ invaild"
)
;
@
interface
MyClass
:
NSObject
{
NSLock *
lock
;
}
@
end
@
implementation
MyClass
-
(
id
)
init
{
self
=
[
super
init
]
;
if
(
self
)
{
lock
=
[
[
NSLock
alloc
]
init
]
;
}
return
self
;
}
-
(
void
)
test1
{
QUARD
(
lock
)
NSLog
(
@
"do test1"
)
;
}
-
(
void
)
test2
{
QUARD
(
lock
)
NSLog
(
@
"do test2"
)
;
}
@
end
|