<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Rust on codedump notes</title>
    <link>https://www.codedump.info/zh/tags/rust/</link>
    <description>Recent content in Rust on codedump notes</description>
    <generator>Hugo</generator>
    <language>zh</language>
    <lastBuildDate>Sat, 25 Jun 2022 10:00:49 +0800</lastBuildDate>
    <atom:link href="https://www.codedump.info/zh/tags/rust/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>周刊（第20期）：Rust并发安全相关的几个概念(下)</title>
      <link>https://www.codedump.info/zh/post/20220625-weekly-20/</link>
      <pubDate>Sat, 25 Jun 2022 10:00:49 +0800</pubDate>
      <guid>https://www.codedump.info/zh/post/20220625-weekly-20/</guid>
      <description>&lt;hr&gt;&#xA;&lt;p&gt;引言：本文介绍Rust并发安全相关的几个概念：&lt;code&gt;Send&lt;/code&gt;、&lt;code&gt;Sync&lt;/code&gt;、&lt;code&gt;Arc&lt;/code&gt;，&lt;code&gt;Mutex&lt;/code&gt;、&lt;code&gt;RwLock&lt;/code&gt;等之间的联系。这是其中的下篇，主要介绍&lt;code&gt;Arc&lt;/code&gt;，&lt;code&gt;Mutex&lt;/code&gt;、&lt;code&gt;RwLock&lt;/code&gt;这几个线程安全相关的类型。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h1 class=&#34;heading&#34; id=&#34;rust并发安全相关的几个概念下&#34;&gt;&#xA;  Rust并发安全相关的几个概念（下）&#xA;  &lt;a class=&#34;anchor&#34; href=&#34;#rust%e5%b9%b6%e5%8f%91%e5%ae%89%e5%85%a8%e7%9b%b8%e5%85%b3%e7%9a%84%e5%87%a0%e4%b8%aa%e6%a6%82%e5%bf%b5%e4%b8%8b&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&lt;p&gt;在&lt;a href=&#34;https://www.codedump.info/post/20220619-weekly-19/&#34;&gt;上一节&lt;/a&gt;中，讲解了&lt;code&gt;Send&lt;/code&gt;和&lt;code&gt;Sync&lt;/code&gt;这两个线程安全相关的&lt;code&gt;trait&lt;/code&gt;，在此基础上展开其它相关类型的讲解。&lt;/p&gt;&#xA;&lt;h2 class=&#34;heading&#34; id=&#34;rc&#34;&gt;&#xA;  Rc&#xA;  &lt;a class=&#34;anchor&#34; href=&#34;#rc&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;Rc&lt;/code&gt;是&lt;code&gt;Reference Counted（引用计数）&lt;/code&gt;的简写，在Rust中，这个数据结构用于实现单线程安全的对指针的引用计数。之所以这个数据结构只是单线程安全，是因为在定义中显式声明了并不实现&lt;code&gt;Send&lt;/code&gt;和&lt;code&gt;Sync&lt;/code&gt;这两个&lt;code&gt;trait&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;#[stable(feature = &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;rust1&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;, since = &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;1.0.0&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;)]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;impl&lt;/span&gt;&amp;lt;T: ?&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;Sized&lt;/span&gt;&amp;gt; !marker::&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;Send&lt;/span&gt; &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;for&lt;/span&gt; Rc&amp;lt;T&amp;gt; {}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;#[stable(feature = &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;rust1&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;, since = &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;1.0.0&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;)]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;impl&lt;/span&gt;&amp;lt;T: ?&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;Sized&lt;/span&gt;&amp;gt; !marker::&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;Sync&lt;/span&gt; &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;for&lt;/span&gt; Rc&amp;lt;T&amp;gt; {}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;个中原因，是因为&lt;code&gt;Rc&lt;/code&gt;内部的实现中，使用了非原子的引用计数（non-atomic reference counting），因此就不能满足线程安全的条件了。如果要在多线程中使用引用计数，就要使用&lt;code&gt;Arc&lt;/code&gt;这个类型：&lt;/p&gt;&#xA;&lt;h2 class=&#34;heading&#34; id=&#34;arc&#34;&gt;&#xA;  Arc&#xA;  &lt;a class=&#34;anchor&#34; href=&#34;#arc&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;与&lt;code&gt;Rc&lt;/code&gt;不同的是，&lt;code&gt;Arc&lt;/code&gt;内部使用了原子操作来实现其引用计数，因此&lt;code&gt;Arc&lt;/code&gt;是&lt;code&gt;Atomically Reference Counted（原子引用计数）&lt;/code&gt;的简写，能被使用在多线程环境中，缺陷是原子操作的性能消耗会更大一些。&lt;/p&gt;&#xA;&lt;p&gt;虽然&lt;code&gt;Arc&lt;/code&gt;能被用在多线程环境中，并不意味着&lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;/code&gt;天然就实现了&lt;code&gt;Send&lt;/code&gt;和&lt;code&gt;Sync&lt;/code&gt;，来看看这两部分的声明：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;#[stable(feature = &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;rust1&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;, since = &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;1.0.0&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;)]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;unsafe&lt;/span&gt; &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;impl&lt;/span&gt;&amp;lt;T: ?&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;Sized&lt;/span&gt; + &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;Sync&lt;/span&gt; + &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;Send&lt;/span&gt;&amp;gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;Send&lt;/span&gt; &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;for&lt;/span&gt; Arc&amp;lt;T&amp;gt; {}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;#[stable(feature = &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;rust1&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;, since = &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;1.0.0&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;)]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;unsafe&lt;/span&gt; &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;impl&lt;/span&gt;&amp;lt;T: ?&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;Sized&lt;/span&gt; + &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;Sync&lt;/span&gt; + &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;Send&lt;/span&gt;&amp;gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;Sync&lt;/span&gt; &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;for&lt;/span&gt; Arc&amp;lt;T&amp;gt; {}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;从声明可以看出：一个&lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;/code&gt;类型，当且仅当包裹（wrap）的类型&lt;code&gt;T&lt;/code&gt;满足&lt;code&gt;Sync&lt;/code&gt;和&lt;code&gt;Send&lt;/code&gt;时才能被认为是满足&lt;code&gt;Send&lt;/code&gt;和&lt;code&gt;Sync&lt;/code&gt;的类型。来做一个实验：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;#![feature(negative_impls)]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;use&lt;/span&gt; std::sync::Arc;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;#[derive(Debug)]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Foo&lt;/span&gt; {}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;impl&lt;/span&gt; !&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;Send&lt;/span&gt; &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;for&lt;/span&gt; Foo {}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; foo = Arc::new(Foo {});&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std::thread::spawn(&lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;move&lt;/span&gt; || {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        dbg!(foo);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在以上的代码中，由于在第8行显示声明了&lt;code&gt;Foo&lt;/code&gt;这个类型不满足&lt;code&gt;Sync&lt;/code&gt;，所以这段代码编译不过，报错信息如下：&lt;/p&gt;</description>
    </item>
    <item>
      <title>周刊（第19期）：Rust并发安全相关的几个概念(上)</title>
      <link>https://www.codedump.info/zh/post/20220619-weekly-19/</link>
      <pubDate>Sun, 19 Jun 2022 10:42:40 +0800</pubDate>
      <guid>https://www.codedump.info/zh/post/20220619-weekly-19/</guid>
      <description>&lt;hr&gt;&#xA;&lt;p&gt;引言：本文介绍Rust并发安全相关的几个概念：&lt;code&gt;Send&lt;/code&gt;、&lt;code&gt;Sync&lt;/code&gt;、&lt;code&gt;Arc&lt;/code&gt;，&lt;code&gt;Mutex&lt;/code&gt;、&lt;code&gt;RwLock&lt;/code&gt;等之间的联系。这是其中的上篇，主要介绍&lt;code&gt;Send&lt;/code&gt;、&lt;code&gt;Sync&lt;/code&gt;这两个&lt;code&gt;trait&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h1 class=&#34;heading&#34; id=&#34;rust并发安全相关的几个概念上&#34;&gt;&#xA;  Rust并发安全相关的几个概念（上）&#xA;  &lt;a class=&#34;anchor&#34; href=&#34;#rust%e5%b9%b6%e5%8f%91%e5%ae%89%e5%85%a8%e7%9b%b8%e5%85%b3%e7%9a%84%e5%87%a0%e4%b8%aa%e6%a6%82%e5%bf%b5%e4%b8%8a&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&lt;h2 class=&#34;heading&#34; id=&#34;rust的所有权概念&#34;&gt;&#xA;  Rust的所有权概念&#xA;  &lt;a class=&#34;anchor&#34; href=&#34;#rust%e7%9a%84%e6%89%80%e6%9c%89%e6%9d%83%e6%a6%82%e5%bf%b5&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;在展开介绍并发相关的几个概念之前，有必要先了解一下Rust的所有权概念，Rust对值（value）的所有权有明确的限制：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;一个值只能有一个owner。&lt;/li&gt;&#xA;&lt;li&gt;可以同时存在同一个值的多个共享的非可变引用（immutable reference）。&lt;/li&gt;&#xA;&lt;li&gt;但是只能存在一个值的可变引用（mutable reference）。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;比如下面这段代码，user在创建线程之后，被移动（move）到两个不同的线程中：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn main() {&#xA;    let user = User { name: &amp;#34;drogus&amp;#34;.to_string() };&#xA;&#xA;    let t1 = spawn(move || {&#xA;        println!(&amp;#34;Hello from the first thread {}&amp;#34;, user.name);&#xA;    });&#xA;&#xA;    let t2 = spawn(move || {&#xA;        println!(&amp;#34;Hello from the second thread {}&amp;#34;, user.name);&#xA;    });&#xA;&#xA;    t1.join().unwrap();&#xA;    t2.join().unwrap();&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;由于&lt;code&gt;一个值只能有一个owner&lt;/code&gt;，所以编译器报错，报错信息如下：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;error[E0382]: use of moved value: `user.name`&#xA;  --&amp;gt; src/main.rs:15:20&#xA;   |&#xA;11 |     let t1 = spawn(move || {&#xA;   |                    ------- value moved into closure here&#xA;12 |         println!(&amp;#34;Hello from the first thread {}&amp;#34;, user.name);&#xA;   |                                                    --------- variable moved due to use in closure&#xA;...&#xA;15 |     let t2 = spawn(move || {&#xA;   |                    ^^^^^^^ value used here after move&#xA;16 |         println!(&amp;#34;Hello from the second thread {}&amp;#34;, user.name);&#xA;   |                                                    --------- use occurs due to use in closure&#xA;   |&#xA;   = note: move occurs because `user.name` has type `String`, which does not implement the `Copy` trait&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h2 class=&#34;heading&#34; id=&#34;send和sync的约束作用&#34;&gt;&#xA;  Send和Sync的约束作用&#xA;  &lt;a class=&#34;anchor&#34; href=&#34;#send%e5%92%8csync%e7%9a%84%e7%ba%a6%e6%9d%9f%e4%bd%9c%e7%94%a8&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;于是，如果一个类型会被多个线程所使用，是需要明确说明其共享属性的。&lt;code&gt;Send&lt;/code&gt;和&lt;code&gt;Sync&lt;/code&gt;这两个&lt;code&gt;trait&lt;/code&gt;作用就在于此，注意到这两个&lt;code&gt;trait&lt;/code&gt;都是&lt;code&gt;std::marker&lt;/code&gt;，实现这两个&lt;code&gt;trait&lt;/code&gt;并不需要对应实现什么方法，可以理解为这两个&lt;code&gt;trait&lt;/code&gt;是类型的&lt;code&gt;约束&lt;/code&gt;，编译器通过这些&lt;code&gt;约束&lt;/code&gt;在编译时对类型进行检查。到目前为止，暂时不展开对两个概念的理解，先来看看两者是如何在类型检查中起&lt;code&gt;约束&lt;/code&gt;作用的。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
