自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深入研究Rust的內(nèi)部可變性- Cell是如何工作的?

開發(fā) 前端
可變引用則不然,顧名思義,可變引用允許我們改變它們所指向的值。所以在這種情況下,對(duì)值有多個(gè)引用是不行的。例如,考慮兩個(gè)線程,其中每個(gè)線程都持有一個(gè)獨(dú)占引用并同時(shí)更改其值。線程運(yùn)行后的值應(yīng)該是什么?確切地說,這是一個(gè)未定義的行為!

在Rust中,我們從引用借用的規(guī)則中知道有不可變(共享)引用和可變(獨(dú)占)引用。

如果我們有一個(gè)共享引用,我們可以想要多少就有多少。這是因?yàn)檫@些引用不允許我們改變它們指向的值,所以同時(shí)有多個(gè)引用是可以的。

可變引用則不然,顧名思義,可變引用允許我們改變它們所指向的值。所以在這種情況下,對(duì)值有多個(gè)引用是不行的。例如,考慮兩個(gè)線程,其中每個(gè)線程都持有一個(gè)獨(dú)占引用并同時(shí)更改其值。線程運(yùn)行后的值應(yīng)該是什么?確切地說,這是一個(gè)未定義的行為!

那么為什么Rust允許我們擁有可共享的可變?nèi)萜髂兀窟@不是打破了Rust的借用規(guī)則嗎?這是因?yàn)檫@些容器有限制,允許以安全的方式使用它們,同時(shí)仍然提供允許可變的api。這就是為什么這些類型提供“內(nèi)部可變性”,當(dāng)使用它們時(shí),它們作為容器施加限制,在這些限制下,它們所持有的類型可以被安全地修改!

Cell 如何提供內(nèi)部可變性?

基本上,Cell通過確保沒有指向其保存的數(shù)據(jù)的指針并且在單線程環(huán)境中執(zhí)行來實(shí)現(xiàn)這一點(diǎn)。

有了這些限制,更改Cell中的數(shù)據(jù)是完全可以的。想想看,如果我們知道Cell中沒有指向數(shù)據(jù)的指針,并且它不是跨線程共享的,則可以保證我們對(duì)它具有獨(dú)占訪問權(quán)。

現(xiàn)在的問題是,Cell是如何施加這些約束的?Cell通過從不返回對(duì)其內(nèi)部數(shù)據(jù)的引用來實(shí)現(xiàn)這一點(diǎn),它總是返回?cái)?shù)據(jù)的副本。因此,這已經(jīng)告訴Cell適用于內(nèi)存開銷小的類型,例如整數(shù)。

此外,Cell沒有實(shí)現(xiàn)Sync,因此它不能在線程邊界之間共享。

Cell的構(gòu)建塊是UnsafeCell,這是Rust內(nèi)部可變性的構(gòu)建塊之一。UnsafeCell允許我們?cè)谌魏螘r(shí)候獲得一個(gè)原始的獨(dú)占指針,指向它所保存的數(shù)據(jù)。這當(dāng)然是一個(gè)不安全的操作,所以我們必須在unsafe{}塊中進(jìn)行操作。

Cell的一種可能的簡(jiǎn)化實(shí)現(xiàn)是:

use std::cell::UnsafeCell;

struct Cell<T> {
    value: UnsafeCell<T>
}

// 禁止跨線程使用Cell
impl<T> !Sync for Cell<T> {}

impl<T> Cell<T> {
    pub fn new(value: T) -> Self {
        Cell { value: UnsafeCell::new(value) }
    }

    pub fn set(self, value: T) {
        // 用一個(gè)新值覆蓋單元格所指向的值
        unsafe { *self.value.get() = value }
    }

    pub fn get(&self) -> T where T: Copy {
        // 返回Cell所指向的數(shù)據(jù)的副本
        unsafe { *self.value.get() }
    }
}

這里我們使用UnsafeCell來存儲(chǔ)Cell的數(shù)據(jù),不允許在線程之間共享此類型,最后,我們從不引用Cell中的數(shù)據(jù)。注意,get方法只適用于實(shí)現(xiàn)Copy的類型,并且返回內(nèi)部類型的副本。

在本文中,我們探討了Rust的Cell類型,我們了解到Cell通過對(duì)其持有的數(shù)據(jù)施加約束來允許內(nèi)部可變性。

責(zé)任編輯:武曉燕 來源: coding到燈火闌珊
相關(guān)推薦

2021-08-26 09:01:35

內(nèi)部Rust可變性

2023-10-30 23:38:03

Rust編程基礎(chǔ)

2011-12-15 10:43:20

JavaNIO

2017-06-06 11:29:23

Java異常研究與分析

2016-01-12 18:04:55

Java異常研究

2010-05-31 17:45:50

MySQL行鎖

2010-06-21 13:07:14

2022-05-11 09:03:05

CSS容器文本換行

2011-06-01 10:58:54

Android Service

2010-05-19 14:45:46

2009-12-08 18:45:17

PHP檢查函數(shù)可用

2013-01-07 13:38:56

Android開發(fā)布局長(zhǎng)度單位

2021-05-25 09:00:00

Kubernetes容器集群

2016-10-21 10:36:54

http2spdynode.js

2010-11-18 17:24:27

Oracle旋轉(zhuǎn)ins

2010-11-23 16:35:59

MySQL刪除多表數(shù)據(jù)

2018-12-24 15:00:58

混合云多云云采用

2022-07-14 23:27:57

數(shù)據(jù)分析數(shù)據(jù)驅(qū)動(dòng)可變數(shù)據(jù)

2012-10-18 09:34:57

CSSdisplayDIV

2010-08-23 17:47:33

DHCP服務(wù)器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)