RcはSend, Syncではない
nomicon:
- A type is Send if it is safe to send it to another thread.
- A type is Sync if it is safe to share between threads (T is Sync if and only if
&Tis Send).
Rcはatomicではないカウンタを持っている。このとき、
Sync:- 惜しい「
&Rcとして勝手にシェアされると参照カウンタを上げ下げできないのでダメ」…通常borrowを渡す分には問題ない。そのborrowがdropされるとしても、もとのRcにはなんら影響がないからだ。参照カウンタの「参照」はborrowを指すのではない(borrowはコンパイル時にチェックされるが、Rcはそれを動的にやるためのもの)。 - 問題は
&RcをcloneしてRcを作れてしまう点にある。&RcがRc: Sync(=&Rc: Send)によって複数のスレッドにちらばっている状態で、同時にcloneされうる。これではnon-atomicなカウントを複数のスレッドから同時に書き換えることになるのでダメ。一方ArcはSyncになりうる。
- 惜しい「
Send: 複数のスレッドにshared ownershipを与えるのではなく、ただexclusive ownershipを移すだけ。ここでSendを与えたとすると、Syncのとき同様に、Send + Cloneによって複数のスレッドにちらばっている状態で、同時にdrop, cloneされうる。これではnon-atomicなカウントを複数のスレッドから同時に書き換えることになるのでダメ。一方カウンタをatomicにさえしてしまえば、複数のdropを順序よく扱えるのでArcはSendになりうる。
よってSend, Syncではない。具体的な実装を盛り込めないmarkerである Send, Syncの役割を、具体的な実装で書ける(参照カウンタを上げ下げできる)CloneとDropで肩代わりしているとも言える。
std::marker::Send,Sync のofficial docsとNomiconと以下を見比べるのがよさそう。
https://stackoverflow.com/questions/59428096/understanding-the-send-trait
https://limpet.net/mbrubeck/2019/02/07/rust-a-unique-perspective.html より:
T: Sendmeans it’s safe to access aTon a single other thread, where one thread at a time has exclusive access. A value of this type can be moved to another thread by unique ownership, or borrowed on another thread by unique reference (&mut T). A more descriptive name for this trait might beUniqueThreadSafe.T: Syncmeans it’s safe for many threads to access aTsimultaneously, with each thread having shared access. Values of such types can be accessed on other threads via shared ownership or shared references (&T). A more descriptive name would beSharedThreadSafe.
https://nyanpasu64.github.io/blog/an-unsafe-tour-of-rust-s-send-and-sync/ ちとよくわからん