Objective-C
- atomicity -
Objective-C
- atomicity -
〜~ 誰もが知ってるかもしれない最初の話 〜~〜~ 誰もが知ってるかもしれない最初の話 〜~
EZ-‐‑‒NET  熊⾕谷友宏 @EasyS...
今回は、ここのお話
⾃自⼰己紹介
@EasyStyleGK
EZ-‐‑‒NET  IP  Phone ⾳音で再配達ゴッド
⾳音で再配達 ⾳音でダイヤル いつもの電卓
for  iPad
いつもの電卓
for  iPhone
iOS  アプリ
制作中
iOS  アプ...
はじまり
1. nonatomic  ってなんだろう
2. なぜ今頃 atomic  の話題なのか
3. @property (atomic)って何をしてくれるの?
4. 値が壊れる?
5. スレッドセーフを考慮する
1. nonatomic ...
第1章
nonatomic って
なんだろう
nonatomic って
なんだろう
nonatomic  と⾔言えば
1. プロパティ定義で使うキーワード
2. atomic  と nonatomic  とがある
3. 省省略略時は atomic  になる
1. プロパティ定義で使うキーワード
2. atomic  と non...
原⼦子性とは
これ以上分解できない単位これ以上分解できない単位
つまり atomic  なプロパティとは
そのプロパティの処理理を
ひとまとまりとして実⾏行行する
そのプロパティの処理理を
ひとまとまりとして実⾏行行する
ということ?ということ?
つまり atomic  なプロパティとは
つまりスレッドセーフ
ということ?
つまりスレッドセーフ
ということ?
必ずしもそうとは限らない必ずしもそうとは限らない
第2章
なぜ今頃
atomic の話題なのか
なぜ今頃
atomic の話題なのか
それは無計画さが招いた課題
1. EXC_̲BAD_̲ACCESS  で落落ちる
2. 計算中に結果を取得される
3. 状態に基づく処理理中に状態が変わる
1. EXC_̲BAD_̲ACCESS  で落落ちる
2. 計算中に結果を取得される
3...
スレッドセーフってなんだろう
1. 他スレッドで使⽤用中のインスタンスが
解放されないようにする
2. 複数スレッドからのアクセス時に、
値に⽭矛盾が出ない事を保証する
3. ⼀一連の処理理をブロックして、⽭矛盾のな
い処理理を保証する
1. ...
スレッドセーフというのは
atomic  はそのうちのひとつatomic  はそのうちのひとつ
複数スレッドを使った平⾏行行処理理を
⽭矛盾しないように制御する考え⽅方
複数スレッドを使った平⾏行行処理理を
⽭矛盾しないように制御する考え⽅方
第3章
@property (atomic) って
何をしてくれるの?
@property (atomic) って
何をしてくれるの?
それとも⾃自分で原⼦子性を
保証しなければいけないの?
それとも⾃自分で原⼦子性を
保証しなければいけないの?
原⼦子性をコンパイラが
⾃自動で保証してくれるの?
原⼦子性をコンパイラが
⾃自動で保証してくれるの?
プロパティに atomic ...
@synthesize  であれば
ある程度度は⾃自動で保証してくれる
@synthesize  であれば
ある程度度は⾃自動で保証してくれる
このあたりの感覚は
@property  (copy)  と同じ
このあたりの感覚は
@proper...
@synthesize  での atomic  制御
読み書きする値が
正しいことを保証する
読み書きする値が
正しいことを保証する
1. インスタンス変数に書き込んでいる間、
他からの読み書きはブロックされる
1. インスタンス変数に書き込ん...
@synthesize  での atomic  制御
値の正確性と合わせて
インスタンスの⽣生存を保証する
値の正確性と合わせて
インスタンスの⽣生存を保証する
1. インスタンス変数に書き込んでいる間、
他からの読み書きはブロックされる
2....
@synthesize  での atomic  制御
@synthesize  で保証されるのは
該当する ivar  の整合性だけ
@synthesize  で保証されるのは
該当する ivar  の整合性だけ
インスタンス全体の
整合性は保...
オブジェクト全体の整合性を保証したいなら
A. 同時実⾏行行されたくないもの同⼠士をロック
B. クラスを Immutable  で設計する
C. インスタンスを扱うスレッドを統⼀一する
A. 同時実⾏行行されたくないもの同⼠士をロック
B. ...
第4章
値が壊れる?値が壊れる?
同時アクセスされることで
クラス全体の整合性が
崩れることは想像に易易しい
クラス全体の整合性が
崩れることは想像に易易しい
case  1:case  1:
インスタンス
{
int _̲a;
int _̲b;
}
-‐‑‒ (void)setA:(int)a  B:(int)b
{
_̲a =  a;
_̲b =  b;
}
-‐‑‒ (int)total
{
return _̲a +  _̲b;...
同時アクセスされることで
@synthesize  なプロパティが
壊れるってどういうこと?
@synthesize  なプロパティが
壊れるってどういうこと?
case  2:case  2:
インスタンス
{
long  long  _̲val;
}
-‐‑‒ (void)setVal:(long  long)val
{
_̲val =  val;
}
-‐‑‒ (long  long)val
{
return _̲val;
}
{...
プロパティの整合性破壊…
プログラムの1⾏行行が
実⾏行行時の1ステップではない
プログラムの1⾏行行が
実⾏行行時の1ステップではない
インスタンス
{
long  long  _̲val;
}
-‐‑‒ (void)setVal:(long  long)val
{
_̲val =  val;
}
-‐‑‒ (long  long)val
{
return _̲val;
}
{...
同時アクセスされることで
プリミティブ型だって壊れるプリミティブ型だって壊れる
つまりつまり
もちろん構造体も壊れるもちろん構造体も壊れる
同時アクセスされることで
インスタンスが
解放されることも
インスタンスが
解放されることも
case  3:case  3:
インスタンス
@interface  MyClass
{
NSString*  _̲string;
}
@property  (nonatomic,readwrite,rcopy)   NSString*  string;
@end
@impl...
平⾏行行処理理は危険がいっぱい平⾏行行処理理は危険がいっぱい
スレッドセーフってとっても⼤大事スレッドセーフってとっても⼤大事
第5章
スレッドセーフを考慮するスレッドセーフを考慮する
おさらい
同時アクセスが引き起こす不不都合同時アクセスが引き起こす不不都合
A. プリミティブ型のプロパティが扱うデー
タが壊れる
B. プロパティから取得したオブジェクトが
予期せず解放される
C. インスタンスへの同時アクセスにより
その整...
スレッドセーフの実現⽅方法
同時アクセスによる
不不都合からプログラムを守るために
同時アクセスによる
不不都合からプログラムを守るために
A. atomic  と @synthesize  を使⽤用する
B. 返すインスタンスは確実に ret...
同時アクセスからの保護
実例例をいくつか実例例をいくつか
ブロックの⽅方法
Objective-‐‑‒C  で使えるロックの紹介Objective-‐‑‒C  で使えるロックの紹介
a) @synchronized  (self)
―  続くブロック {}  を再帰ロック
―  指定したインスタンスが...
実例例
読み書きでの
値の破壊を防ぐ
読み書きでの
値の破壊を防ぐ
case  A:case  A:
読み書きでの値の破壊を防ぐ
プリミティブ型の @property  (atomic)  を
@synthesize  したときに採られる⽅方法
プリミティブ型の @property  (atomic)  を
@synthesize  したときに...
インスタンス
@interface  MyObject :  NSObject
{
long  long  _̲val;
}
@property  (atomic,readwrite)  long  long val;
@end
@implem...
内部的な実装は次のような感じに
@synthesize  で⽣生成される内部ロックは
@synchronized  (self)  とはまったく別のもの
@synthesize  で⽣生成される内部ロックは
@synchronized  (se...
実例例
インスタンスを
確実に retain  する
インスタンスを
確実に retain  する
case  B:case  B:
インスタンスを確実に retain  する
1. セッターとゲッターを
同じキーでロックする
2. ゲッターのロック内でインスタンス
を retain  &  autorelease  する
1. セッターとゲッターを
同じキーでロックする
2...
インスタンス
@interface  MyClass
{
NSString*  _̲string;
}
@property  (atomic,readwrite,copy)  NSString* string;
@end
@implementa...
内部的な実装は次のような感じに
親インスタンスの dealloc  で _̲string  が
解放されるところまでは保護されない
親インスタンスの dealloc  で _̲string  が
解放されるところまでは保護されない
Setter...
実例例
関係する範囲をロックして
不不整合が起きないようにする
関係する範囲をロックして
不不整合が起きないようにする
case  C:case  C:
関係する範囲をロックして不不整合を防ぐ
1. 同時アクセスされたくない部分を
同じキーでロックする
2. プロパティも含めて保護するときは
@synthesize  は使わない
1. 同時アクセスされたくない部分を
同じキーでロックする
2. ...
インスタンス
-‐‑‒ (void)setA:(int)a  B:(int)b
{
@synchronized  (self)
{
_̲a =  a;
_̲b =  b;
}
}
-‐‑‒ (int)total
{
@synchronized ...
実例例
実⾏行行するスレッドを
ひとつに統⼀一する
実⾏行行するスレッドを
ひとつに統⼀一する
case  D:case  D:
実⾏行行するスレッドをひとつに統⼀一する
1. ある⼀一連の機能を必ず同じスレッド
で実⾏行行するようにする
2. 実⾏行行スレッドではランループが必要
1. ある⼀一連の機能を必ず同じスレッド
で実⾏行行するようにする
2. 実⾏行行スレッド...
インスタンス
@interface  MyClass
{
NSString*  _̲string;
}
@property  (nonatomic,readwrite,copy)  NSString* string;
@end
@impleme...
実例例
クラスを
Immutable  で設計する
クラスを
Immutable  で設計する
case  E:case  E:
クラスを Immutable  で設計する
インスタンス⽣生成後に
値を変更更できないようにする⽅方法
インスタンス⽣生成後に
値を変更更できないようにする⽅方法
値が「変化する途中」が存在しないため
同時アクセスで値が⽭矛盾しない
値が「変化...
クラスを Immutable  で設計する
ただしインスタンスの受け渡し時には
原⼦子性を保護する必要がある
ただしインスタンスの受け渡し時には
原⼦子性を保護する必要がある
Immutable  クラスの特徴Immutable  クラスの特徴...
クラスを Immutable  で設計する
値は init  メソッドで設定して
インスタンス⽣生成後は値の取得だけができる
値は init  メソッドで設定して
インスタンス⽣生成後は値の取得だけができる
クラス定義
@interface M...
クラスを Immutable  で設計する
クラス実装
@implementation  MyClass
-‐‑‒ (id)initWithA:(long  long)a  B:(long  long)b
{
self  =  [super  ...
インスタンス
@interface  TestClass
{
MyClass*  _̲obj;
}
@property  (atomic,readwrite,retain)   MyClass*  obj;
@end
@implementati...
他のケース
他にもこんなところで
配慮されていたり
他にもこんなところで
配慮されていたり
1.予期しないインスタンスの解放を防ぐ
他のスレッドで実⾏行行されるまでの間に
インスタンスが解放されないようにする
他のスレッドで実⾏行行されるまでの間に
インスタンスが解放されないようにする
1. 引数 withObject に渡されたイン...
2.予期しない値の変化を防ぐ
渡された NSString  を
複製してインスタンス変数に持つ⽅方法
渡された NSString  を
複製してインスタンス変数に持つ⽅方法
複製を内部に持つ事で
外部での値変更更の影響を受けない
複製を内部に持...
スレッドセーフ
このような配慮で
複数スレッドに対応させている
このような配慮で
複数スレッドに対応させている
あとは宣伝 ...あとは宣伝 ...
本日リリースしました。本日リリースしました。
⾳音で再配達ゴッド⾳音で再配達ゴッド
• 不不在票の再配達⼿手配を
お⼿手伝いするアプリです。
• 有料料版は iPhone  の携帯回線だ
けでも⼿手配ができます。
• 無料料版はトーンにした操作...
Upcoming SlideShare
Loading in …5
×

Objective-C atomicity #idevjp

1,572 views

Published on

Objective-C の @property でおなじみの atomic について、iphone_dev_jp 東京 iPhone/Mac 勉強会で発表しました。

atomic でどんな作用が期待できるのか。
それがスレッドセーフになり得るのか。
スレッドセーフを実現するための手法とは。

今回はそんな、マルチスレッド周りのお話です。

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,572
On SlideShare
0
From Embeds
0
Number of Embeds
537
Actions
Shares
0
Downloads
0
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Objective-C atomicity #idevjp

  1. 1. Objective-C - atomicity - Objective-C - atomicity - 〜~ 誰もが知ってるかもしれない最初の話 〜~〜~ 誰もが知ってるかもしれない最初の話 〜~ EZ-‐‑‒NET  熊⾕谷友宏 @EasyStyleGK http://program.station.ez-‐‑‒net.jp/
  2. 2. 今回は、ここのお話
  3. 3. ⾃自⼰己紹介 @EasyStyleGK EZ-‐‑‒NET  IP  Phone ⾳音で再配達ゴッド ⾳音で再配達 ⾳音でダイヤル いつもの電卓 for  iPad いつもの電卓 for  iPhone iOS  アプリ 制作中 iOS  アプリ 制作中 EZ-‐‑‒NET  熊⾕谷友宏 http://program.station.ez-‐‑‒net.jp/
  4. 4. はじまり 1. nonatomic  ってなんだろう 2. なぜ今頃 atomic  の話題なのか 3. @property (atomic)って何をしてくれるの? 4. 値が壊れる? 5. スレッドセーフを考慮する 1. nonatomic  ってなんだろう 2. なぜ今頃 atomic  の話題なのか 3. @property (atomic)って何をしてくれるの? 4. 値が壊れる? 5. スレッドセーフを考慮する ⽬目次⽬目次
  5. 5. 第1章 nonatomic って なんだろう nonatomic って なんだろう
  6. 6. nonatomic  と⾔言えば 1. プロパティ定義で使うキーワード 2. atomic  と nonatomic  とがある 3. 省省略略時は atomic  になる 1. プロパティ定義で使うキーワード 2. atomic  と nonatomic  とがある 3. 省省略略時は atomic  になる そのプロパティが原⼦子性を 保証するかを⽰示すキーワード そのプロパティが原⼦子性を 保証するかを⽰示すキーワード
  7. 7. 原⼦子性とは これ以上分解できない単位これ以上分解できない単位
  8. 8. つまり atomic  なプロパティとは そのプロパティの処理理を ひとまとまりとして実⾏行行する そのプロパティの処理理を ひとまとまりとして実⾏行行する ということ?ということ?
  9. 9. つまり atomic  なプロパティとは つまりスレッドセーフ ということ? つまりスレッドセーフ ということ? 必ずしもそうとは限らない必ずしもそうとは限らない
  10. 10. 第2章 なぜ今頃 atomic の話題なのか なぜ今頃 atomic の話題なのか
  11. 11. それは無計画さが招いた課題 1. EXC_̲BAD_̲ACCESS  で落落ちる 2. 計算中に結果を取得される 3. 状態に基づく処理理中に状態が変わる 1. EXC_̲BAD_̲ACCESS  で落落ちる 2. 計算中に結果を取得される 3. 状態に基づく処理理中に状態が変わる ⾃自作アプリの複数スレッドを跨ぐ処理理が いよいよ制御しきれなくなったため! ⾃自作アプリの複数スレッドを跨ぐ処理理が いよいよ制御しきれなくなったため! スレッドセーフを考えなくてはいけないスレッドセーフを考えなくてはいけない
  12. 12. スレッドセーフってなんだろう 1. 他スレッドで使⽤用中のインスタンスが 解放されないようにする 2. 複数スレッドからのアクセス時に、 値に⽭矛盾が出ない事を保証する 3. ⼀一連の処理理をブロックして、⽭矛盾のな い処理理を保証する 1. 他スレッドで使⽤用中のインスタンスが 解放されないようにする 2. 複数スレッドからのアクセス時に、 値に⽭矛盾が出ない事を保証する 3. ⼀一連の処理理をブロックして、⽭矛盾のな い処理理を保証する など、いろいろなど、いろいろ
  13. 13. スレッドセーフというのは atomic  はそのうちのひとつatomic  はそのうちのひとつ 複数スレッドを使った平⾏行行処理理を ⽭矛盾しないように制御する考え⽅方 複数スレッドを使った平⾏行行処理理を ⽭矛盾しないように制御する考え⽅方
  14. 14. 第3章 @property (atomic) って 何をしてくれるの? @property (atomic) って 何をしてくれるの?
  15. 15. それとも⾃自分で原⼦子性を 保証しなければいけないの? それとも⾃自分で原⼦子性を 保証しなければいけないの? 原⼦子性をコンパイラが ⾃自動で保証してくれるの? 原⼦子性をコンパイラが ⾃自動で保証してくれるの? プロパティに atomic  を指定したとき
  16. 16. @synthesize  であれば ある程度度は⾃自動で保証してくれる @synthesize  であれば ある程度度は⾃自動で保証してくれる このあたりの感覚は @property  (copy)  と同じ このあたりの感覚は @property  (copy)  と同じ
  17. 17. @synthesize  での atomic  制御 読み書きする値が 正しいことを保証する 読み書きする値が 正しいことを保証する 1. インスタンス変数に書き込んでいる間、 他からの読み書きはブロックされる 1. インスタンス変数に書き込んでいる間、 他からの読み書きはブロックされる プリミティブ型の場合プリミティブ型の場合
  18. 18. @synthesize  での atomic  制御 値の正確性と合わせて インスタンスの⽣生存を保証する 値の正確性と合わせて インスタンスの⽣生存を保証する 1. インスタンス変数に書き込んでいる間、 他からの読み書きはブロックされる 2. ゲッターでは、ブロックの中でインスタ ンスを retain  して autorelease  する 1. インスタンス変数に書き込んでいる間、 他からの読み書きはブロックされる 2. ゲッターでは、ブロックの中でインスタ ンスを retain  して autorelease  する オブジェクト型の場合オブジェクト型の場合
  19. 19. @synthesize  での atomic  制御 @synthesize  で保証されるのは 該当する ivar  の整合性だけ @synthesize  で保証されるのは 該当する ivar  の整合性だけ インスタンス全体の 整合性は保証されない インスタンス全体の 整合性は保証されない
  20. 20. オブジェクト全体の整合性を保証したいなら A. 同時実⾏行行されたくないもの同⼠士をロック B. クラスを Immutable  で設計する C. インスタンスを扱うスレッドを統⼀一する A. 同時実⾏行行されたくないもの同⼠士をロック B. クラスを Immutable  で設計する C. インスタンスを扱うスレッドを統⼀一する メソッドでの処理理も考慮した インスタンス全体の整合性を保つ制御が必要 メソッドでの処理理も考慮した インスタンス全体の整合性を保つ制御が必要 こういったことに配慮しながら クラスを設計する必要がある こういったことに配慮しながら クラスを設計する必要がある
  21. 21. 第4章 値が壊れる?値が壊れる?
  22. 22. 同時アクセスされることで クラス全体の整合性が 崩れることは想像に易易しい クラス全体の整合性が 崩れることは想像に易易しい case  1:case  1:
  23. 23. インスタンス { int _̲a; int _̲b; } -‐‑‒ (void)setA:(int)a  B:(int)b { _̲a =  a; _̲b =  b; } -‐‑‒ (int)total { return _̲a +  _̲b; } { int _̲a; int _̲b; } -‐‑‒ (void)setA:(int)a  B:(int)b { _̲a =  a; _̲b =  b; } -‐‑‒ (int)total { return _̲a +  _̲b; } クラス全体の整合性破壊 スレッド 1 スレッド 2 [obj  setA:3  B:5];[obj  setA:3  B:5]; 6 [obj  setA:1  B:3];[obj  setA:1  B:3]; [obj  total];[obj  total];a  ⇦  1 [3] b  ⇦ 3 [5] 4 a  ⇦  3 [1] b  ⇦ 5 [2] 8 ⏎ 1   +  5 [4] ?
  24. 24. 同時アクセスされることで @synthesize  なプロパティが 壊れるってどういうこと? @synthesize  なプロパティが 壊れるってどういうこと? case  2:case  2:
  25. 25. インスタンス { long  long  _̲val; } -‐‑‒ (void)setVal:(long  long)val { _̲val =  val; } -‐‑‒ (long  long)val { return _̲val; } { long  long  _̲val; } -‐‑‒ (void)setVal:(long  long)val { _̲val =  val; } -‐‑‒ (long  long)val { return _̲val; } プロパティの整合性破壊? スレッド 1 スレッド 2 obj.val  =  1;obj.val  =  1; 4294967295 1 -‐‑‒1 obj.val  =  -‐‑‒1obj.val  =  -‐‑‒1 obj.val;obj.val; !?_̲val ⇦  -‐‑‒1 [2] _̲val ⇦  1 [1] ⏎ -‐‑‒1[3]
  26. 26. プロパティの整合性破壊… プログラムの1⾏行行が 実⾏行行時の1ステップではない プログラムの1⾏行行が 実⾏行行時の1ステップではない
  27. 27. インスタンス { long  long  _̲val; } -‐‑‒ (void)setVal:(long  long)val { _̲val =  val; } -‐‑‒ (long  long)val { return _̲val; } { long  long  _̲val; } -‐‑‒ (void)setVal:(long  long)val { _̲val =  val; } -‐‑‒ (long  long)val { return _̲val; } プロパティの整合性破壊! スレッド 1 スレッド 2 obj.val  =  1;obj.val  =  1; 4294967295 obj.val  =  -‐‑‒1obj.val  =  -‐‑‒1 obj.val;obj.val; 下位ビット [3] 上位 ビット [6] -‐‑‒1 下位ビット [1] 上位 ビット [2] 1 下位ビット [4] 上位 ビット [5] !
  28. 28. 同時アクセスされることで プリミティブ型だって壊れるプリミティブ型だって壊れる つまりつまり もちろん構造体も壊れるもちろん構造体も壊れる
  29. 29. 同時アクセスされることで インスタンスが 解放されることも インスタンスが 解放されることも case  3:case  3:
  30. 30. インスタンス @interface  MyClass { NSString*  _̲string; } @property  (nonatomic,readwrite,rcopy)   NSString*  string; @end @implementation MyClass @synthesize  string  = _̲string; @end @interface  MyClass { NSString*  _̲string; } @property  (nonatomic,readwrite,rcopy)   NSString*  string; @end @implementation MyClass @synthesize  string  = _̲string; @end インスタンスの予期しない解放 スレッド 1 スレッド 2 string  =  [obj.string  retain];string  =  [obj.string  retain]; [string retain] [3] Bad  Access  ! ⏎   _̲string [1] [_̲string   release] [2] _̲string  =   [ssss copy] [4] obj.string  =  ssss;obj.string  =  ssss;
  31. 31. 平⾏行行処理理は危険がいっぱい平⾏行行処理理は危険がいっぱい スレッドセーフってとっても⼤大事スレッドセーフってとっても⼤大事
  32. 32. 第5章 スレッドセーフを考慮するスレッドセーフを考慮する
  33. 33. おさらい 同時アクセスが引き起こす不不都合同時アクセスが引き起こす不不都合 A. プリミティブ型のプロパティが扱うデー タが壊れる B. プロパティから取得したオブジェクトが 予期せず解放される C. インスタンスへの同時アクセスにより その整合性が崩れる A. プリミティブ型のプロパティが扱うデー タが壊れる B. プロパティから取得したオブジェクトが 予期せず解放される C. インスタンスへの同時アクセスにより その整合性が崩れる
  34. 34. スレッドセーフの実現⽅方法 同時アクセスによる 不不都合からプログラムを守るために 同時アクセスによる 不不都合からプログラムを守るために A. atomic  と @synthesize  を使⽤用する B. 返すインスタンスは確実に retain  する C. 関係する範囲を把握して 不不整合が起こらないようにロックする D. 実⾏行行するスレッドをひとつに統⼀一する E. クラスを Immutable  で設計する A. atomic  と @synthesize  を使⽤用する B. 返すインスタンスは確実に retain  する C. 関係する範囲を把握して 不不整合が起こらないようにロックする D. 実⾏行行するスレッドをひとつに統⼀一する E. クラスを Immutable  で設計する
  35. 35. 同時アクセスからの保護 実例例をいくつか実例例をいくつか
  36. 36. ブロックの⽅方法 Objective-‐‑‒C  で使えるロックの紹介Objective-‐‑‒C  で使えるロックの紹介 a) @synchronized  (self) ―  続くブロック {}  を再帰ロック ―  指定したインスタンスがキーになる b) NSRecursiveLock ―  -‐‑‒lock  から -‐‑‒unlock  までを再帰ロック ―  pthread_̲mutex  の Objective-‐‑‒C  版 c) セマフォ ―  dispatch_̲semaphore  でロック ―  タイムアウトの指定も可能 a) @synchronized  (self) ―  続くブロック {}  を再帰ロック ―  指定したインスタンスがキーになる b) NSRecursiveLock ―  -‐‑‒lock  から -‐‑‒unlock  までを再帰ロック ―  pthread_̲mutex  の Objective-‐‑‒C  版 c) セマフォ ―  dispatch_̲semaphore  でロック ―  タイムアウトの指定も可能
  37. 37. 実例例 読み書きでの 値の破壊を防ぐ 読み書きでの 値の破壊を防ぐ case  A:case  A:
  38. 38. 読み書きでの値の破壊を防ぐ プリミティブ型の @property  (atomic)  を @synthesize  したときに採られる⽅方法 プリミティブ型の @property  (atomic)  を @synthesize  したときに採られる⽅方法 1. セッターとゲッターを 同じキーでロックする 1. セッターとゲッターを 同じキーでロックする 同時アクセスを防ぎ 値の⽭矛盾を起こさない 同時アクセスを防ぎ 値の⽭矛盾を起こさない
  39. 39. インスタンス @interface  MyObject :  NSObject { long  long  _̲val; } @property  (atomic,readwrite)  long  long val; @end @implementation MyObject @synthesize  val  =  _̲val; @end @interface  MyObject :  NSObject { long  long  _̲val; } @property  (atomic,readwrite)  long  long val; @end @implementation MyObject @synthesize  val  =  _̲val; @end atomic  キーワードを使⽤用する スレッド 1 スレッド 2 obj.val =  1;obj.val =  1; -‐‑‒1 obj.val  =  -‐‑‒1obj.val  =  -‐‑‒1 obj.val;obj.val; 下位ビット [2] 上位 ビット [2] -‐‑‒1 下位ビット [1] 上位 ビット [1] 1 下位ビット [3] 上位 ビット [3] Lock!Lock! Lock!Lock! Lock!Lock! OK !
  40. 40. 内部的な実装は次のような感じに @synthesize  で⽣生成される内部ロックは @synchronized  (self)  とはまったく別のもの @synthesize  で⽣生成される内部ロックは @synchronized  (self)  とはまったく別のもの Setter -‐‑‒ (void)setVal:(long  long)val { [_̲lock  lock]; _̲val =  val; [_̲lock  unlock]; } -‐‑‒ (void)setVal:(long  long)val { [_̲lock  lock]; _̲val =  val; [_̲lock  unlock]; } Getter -‐‑‒ (long  long)val { [_̲lock  lock]; @try { return _̲val; } @finally { [_̲lock  unlock]; } } -‐‑‒ (long  long)val { [_̲lock  lock]; @try { return _̲val; } @finally { [_̲lock  unlock]; } }
  41. 41. 実例例 インスタンスを 確実に retain  する インスタンスを 確実に retain  する case  B:case  B:
  42. 42. インスタンスを確実に retain  する 1. セッターとゲッターを 同じキーでロックする 2. ゲッターのロック内でインスタンス を retain  &  autorelease  する 1. セッターとゲッターを 同じキーでロックする 2. ゲッターのロック内でインスタンス を retain  &  autorelease  する インスタンスを確実に確保して 呼び出し元が正しく受け取れるようにする インスタンスを確実に確保して 呼び出し元が正しく受け取れるようにする オブジェクト型の @property  (atomic)  を @synthesize  したときに採られる⽅方法 オブジェクト型の @property  (atomic)  を @synthesize  したときに採られる⽅方法
  43. 43. インスタンス @interface  MyClass { NSString*  _̲string; } @property  (atomic,readwrite,copy)  NSString* string; @end @implementation MyClass @synthesize  string  = _̲string; @end @interface  MyClass { NSString*  _̲string; } @property  (atomic,readwrite,copy)  NSString* string; @end @implementation MyClass @synthesize  string  = _̲string; @end インスタンスを確実に retain  する スレッド 1 スレッド 2 string  =  [obj.string  retain];string  =  [obj.string  retain]; [_̲string   release] [2] _̲string  =   [ssss retain] [2] obj.string  =  ssss;obj.string  =  ssss; [string  retain] [3] [_̲string   retain] [1] [_̲string   autorelease] [1] ⏎  _̲string[1] Lock!Lock! Lock!Lock! KEEP! OK !
  44. 44. 内部的な実装は次のような感じに 親インスタンスの dealloc  で _̲string  が 解放されるところまでは保護されない 親インスタンスの dealloc  で _̲string  が 解放されるところまでは保護されない Setter -‐‑‒ (void)setString: (NSString*)string { [_̲lock  lock]; _̲string =  [string  copy]; [_̲lock  unlock]; } -‐‑‒ (void)setString: (NSString*)string { [_̲lock  lock]; _̲string =  [string  copy]; [_̲lock  unlock]; } Getter -‐‑‒ (NSString*)string { [_̲lock  lock]; @try { [_̲string retain]; [_̲string autorelease]; return _̲string; } @finally { [_̲lock  unlock]; } } -‐‑‒ (NSString*)string { [_̲lock  lock]; @try { [_̲string retain]; [_̲string autorelease]; return _̲string; } @finally { [_̲lock  unlock]; } }
  45. 45. 実例例 関係する範囲をロックして 不不整合が起きないようにする 関係する範囲をロックして 不不整合が起きないようにする case  C:case  C:
  46. 46. 関係する範囲をロックして不不整合を防ぐ 1. 同時アクセスされたくない部分を 同じキーでロックする 2. プロパティも含めて保護するときは @synthesize  は使わない 1. 同時アクセスされたくない部分を 同じキーでロックする 2. プロパティも含めて保護するときは @synthesize  は使わない 計算処理理と結果取得を同じキーでロックすれば 計算途中の結果取得を防⽌止できる 計算処理理と結果取得を同じキーでロックすれば 計算途中の結果取得を防⽌止できる オブジェクト全体の 整合性を保護する⽅方法 オブジェクト全体の 整合性を保護する⽅方法
  47. 47. インスタンス -‐‑‒ (void)setA:(int)a  B:(int)b { @synchronized  (self) { _̲a =  a; _̲b =  b; } } -‐‑‒ (int)total { @synchronized  (self) { return _̲a +  _̲b; } } -‐‑‒ (void)setA:(int)a  B:(int)b { @synchronized  (self) { _̲a =  a; _̲b =  b; } } -‐‑‒ (int)total { @synchronized  (self) { return _̲a +  _̲b; } } 整合性に関係する範囲をロックする スレッド 1 スレッド 2 [obj  setA:3  B:5];[obj  setA:3  B:5]; 4 [obj  setA:1  B:3];[obj  setA:1  B:3]; [obj  total];[obj  total]; a  ⇦  1 [2] b  ⇦ 3 [2] 4 a  ⇦  3 [1] b  ⇦ 5 [1] 8 ⏎ 1   +  3 [3] Lock!Lock! Lock!Lock! Lock!Lock! OK !
  48. 48. 実例例 実⾏行行するスレッドを ひとつに統⼀一する 実⾏行行するスレッドを ひとつに統⼀一する case  D:case  D:
  49. 49. 実⾏行行するスレッドをひとつに統⼀一する 1. ある⼀一連の機能を必ず同じスレッド で実⾏行行するようにする 2. 実⾏行行スレッドではランループが必要 1. ある⼀一連の機能を必ず同じスレッド で実⾏行行するようにする 2. 実⾏行行スレッドではランループが必要 同時アクセスを起こさせないため ロックやデータの⽭矛盾を気にしなくて済む 同時アクセスを起こさせないため ロックやデータの⽭矛盾を気にしなくて済む iOS の UI  制御でも採られている⽅方法iOS の UI  制御でも採られている⽅方法
  50. 50. インスタンス @interface  MyClass { NSString*  _̲string; } @property  (nonatomic,readwrite,copy)  NSString* string; @end @implementation MyClass @synthesize  string = _̲string; @end @interface  MyClass { NSString*  _̲string; } @property  (nonatomic,readwrite,copy)  NSString* string; @end @implementation MyClass @synthesize  string = _̲string; @end 実⾏行行するスレッドをひとつに統⼀一する スレッド 1 スレッド 2 string  =  [obj.string  retain];string  =  [obj.string  retain]; [string  retain] [2] [_̲string   release] [3] _̲string  =   [ssss copy] [4] [obj  performSelector:@selector(setString:) onThread:スレッド2 withObject:ssss waitUntilDone:NO]; [obj  performSelector:@selector(setString:) onThread:スレッド2 withObject:ssss waitUntilDone:NO]; No Lock.No Lock. ⏎   _̲string [1] OK !
  51. 51. 実例例 クラスを Immutable  で設計する クラスを Immutable  で設計する case  E:case  E:
  52. 52. クラスを Immutable  で設計する インスタンス⽣生成後に 値を変更更できないようにする⽅方法 インスタンス⽣生成後に 値を変更更できないようにする⽅方法 値が「変化する途中」が存在しないため 同時アクセスで値が⽭矛盾しない 値が「変化する途中」が存在しないため 同時アクセスで値が⽭矛盾しない 1. インスタンス⽣生成後に ivar  の値を編集 できないクラスを作る 2. 値の設定はインスタンス⽣生成のときだけ 1. インスタンス⽣生成後に ivar  の値を編集 できないクラスを作る 2. 値の設定はインスタンス⽣生成のときだけ
  53. 53. クラスを Immutable  で設計する ただしインスタンスの受け渡し時には 原⼦子性を保護する必要がある ただしインスタンスの受け渡し時には 原⼦子性を保護する必要がある Immutable  クラスの特徴Immutable  クラスの特徴 内部でのロックなく 複数スレッドで使⽤用可能 内部でのロックなく 複数スレッドで使⽤用可能
  54. 54. クラスを Immutable  で設計する 値は init  メソッドで設定して インスタンス⽣生成後は値の取得だけができる 値は init  メソッドで設定して インスタンス⽣生成後は値の取得だけができる クラス定義 @interface MyClass  :  NSObject @property  (nonatomic,readonly)  long  long a; @property (nonatomic,readonly)  long  long b; @property (nonatomic,readonly)  long  long  total; -‐‑‒ (id)initWithA:(long  long)a  B:(long  long)b; @end @interface MyClass  :  NSObject @property  (nonatomic,readonly)  long  long a; @property (nonatomic,readonly)  long  long b; @property (nonatomic,readonly)  long  long  total; -‐‑‒ (id)initWithA:(long  long)a  B:(long  long)b; @end
  55. 55. クラスを Immutable  で設計する クラス実装 @implementation  MyClass -‐‑‒ (id)initWithA:(long  long)a  B:(long  long)b { self  =  [super  init]; if (self) { _̲a =  a; _̲b =  b; } return self; } -‐‑‒ (long  long)total { return _̲a +  _̲b; } @implementation  MyClass -‐‑‒ (id)initWithA:(long  long)a  B:(long  long)b { self  =  [super  init]; if (self) { _̲a =  a; _̲b =  b; } return self; } -‐‑‒ (long  long)total { return _̲a +  _̲b; }
  56. 56. インスタンス @interface  TestClass { MyClass*  _̲obj; } @property  (atomic,readwrite,retain)   MyClass*  obj; @end @implementation MyClass @synthesize  obj = _̲obj; @end @interface  TestClass { MyClass*  _̲obj; } @property  (atomic,readwrite,retain)   MyClass*  obj; @end @implementation MyClass @synthesize  obj = _̲obj; @end クラスを Immutable  で設計する スレッド 1 スレッド 2 test.obj =  [[MyClass  alloc]  initWithA:3  B:5];test.obj =  [[MyClass  alloc]  initWithA:3  B:5]; 4 test.obj =  [[MyClass  alloc]  initWithA:1  B:3];test.obj =  [[MyClass  alloc]  initWithA:1  B:3]; [test.obj total];[test.obj total]; _̲obj  =   [obj  retain] [2]4 _̲obj  =   [obj  retain] [1]8 [_̲obj   retain] [3] [_̲obj   autorelease] [3] ⏎  _̲obj[3] Lock!Lock! [test.obj total] [2] Lock!Lock! Lock!Lock! OK !
  57. 57. 他のケース 他にもこんなところで 配慮されていたり 他にもこんなところで 配慮されていたり
  58. 58. 1.予期しないインスタンスの解放を防ぐ 他のスレッドで実⾏行行されるまでの間に インスタンスが解放されないようにする 他のスレッドで実⾏行行されるまでの間に インスタンスが解放されないようにする 1. 引数 withObject に渡されたインスタン スが渡された時点で retain  される 2. 別スレッドでの実⾏行行が終わると、インス タンスは release  される 1. 引数 withObject に渡されたインスタン スが渡された時点で retain  される 2. 別スレッドでの実⾏行行が終わると、インス タンスは release  される performSelector:onThread:withObject :...  によるインスタンスの⽣生存保証 performSelector:onThread:withObject :...  によるインスタンスの⽣生存保証
  59. 59. 2.予期しない値の変化を防ぐ 渡された NSString  を 複製してインスタンス変数に持つ⽅方法 渡された NSString  を 複製してインスタンス変数に持つ⽅方法 複製を内部に持つ事で 外部での値変更更の影響を受けない 複製を内部に持つ事で 外部での値変更更の影響を受けない 1. NSString  のインスタンスは編集可能な 場合がある (NSMutableString) 2. そこで copy  して、渡されたものとは 別の NSString  を持つようにする 1. NSString  のインスタンスは編集可能な 場合がある (NSMutableString) 2. そこで copy  して、渡されたものとは 別の NSString  を持つようにする
  60. 60. スレッドセーフ このような配慮で 複数スレッドに対応させている このような配慮で 複数スレッドに対応させている
  61. 61. あとは宣伝 ...あとは宣伝 ...
  62. 62. 本日リリースしました。本日リリースしました。 ⾳音で再配達ゴッド⾳音で再配達ゴッド • 不不在票の再配達⼿手配を お⼿手伝いするアプリです。 • 有料料版は iPhone  の携帯回線だ けでも⼿手配ができます。 • 無料料版はトーンにした操作⾳音を 固定電話に聞かせて⼿手配します。 • 不不在票の再配達⼿手配を お⼿手伝いするアプリです。 • 有料料版は iPhone  の携帯回線だ けでも⼿手配ができます。 • 無料料版はトーンにした操作⾳音を 固定電話に聞かせて⼿手配します。

×