互斥鎖,自旋鎖灵巧,原子操作原理和實(shí)現(xiàn)

目錄

1. 互斥鎖的實(shí)現(xiàn)與特點(diǎn)
2. 自旋鎖的實(shí)現(xiàn)和特點(diǎn)
3. 原子操作的原理和實(shí)現(xiàn)方式
4. 三種同步方式的應(yīng)用場(chǎng)景

1. 互斥鎖的實(shí)現(xiàn)和特點(diǎn)

  • linux內(nèi)核中關(guān)于互斥鎖的實(shí)現(xiàn)

//數(shù)據(jù)結(jié)構(gòu)(linux2.6之后,之前是采用信號(hào)量定義一個(gè)mutex抹沪,事實(shí)上它的定義還是類(lèi)似于信號(hào)量)
struct mutex {
    /* 1: unlocked, 0: locked, negative: locked, possible waiters */
    atomic_t        count;
    spinlock_t      wait_lock;//自旋鎖刻肄,等待獲取互斥鎖中使用的自旋鎖。在獲取互斥鎖的過(guò)程中采够,操作會(huì)在自旋鎖的保護(hù)中進(jìn)行肄方。初始化為為鎖定冰垄。
    struct list_head    wait_list;//維護(hù)一個(gè)等待隊(duì)列
#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_MUTEX_SPIN_ON_OWNER)
    struct task_struct  *owner;//指向擁有互斥鎖的進(jìn)程
#endif
#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
    struct optimistic_spin_queue osq; /* Spinner MCS lock */
#endif
#ifdef CONFIG_DEBUG_MUTEXES
    void            *magic;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
    struct lockdep_map  dep_map;
#endif
};

如何使用互斥鎖

  • 初始化
    mutex_init(&mutex); //動(dòng)態(tài)初始化互斥鎖
    DEFINE_MUTEX(mutexname); //靜態(tài)定義和初始化互斥鎖
  • 上鎖
    void mutex_lock(struct mutex lock);//無(wú)法獲得鎖時(shí)蹬癌,睡眠等待权她,不會(huì)被信號(hào)中斷。
    int mutex_trylock(struct mutex lock);//此函數(shù)是 mutex_lock()的非阻塞版本逝薪,成功返回1隅要,失敗返回0。
    int mutex_lock_interruptible(struct mutex lock);//和mutex_lock()一樣董济,也是獲取互斥鎖步清。在獲得了互斥鎖或進(jìn)入睡眠直到獲得互斥鎖之后會(huì)返回0。如果在等待獲取鎖的時(shí)候進(jìn)入睡眠狀態(tài)收到一個(gè)信號(hào)(被信號(hào)打斷睡眠)虏肾,則返回_EINIR廓啊。
  • 解鎖
    void mutex_unlock(struct mutex lock);

注意:互斥鎖在上鎖的過(guò)程中,需要用自旋鎖保證原子操作(包括修改原子量和鎖的相關(guān)數(shù)據(jù)結(jié)構(gòu))

  • posix庫(kù)中關(guān)于互斥鎖的實(shí)現(xiàn)(用戶態(tài))

如何使用互斥鎖

  • 初始化
    int pthread_mutex_init(pthread_mutex_t *mp, const pthread_mutexattr_t *mattr);;//動(dòng)態(tài)初始化互斥鎖
    函數(shù)說(shuō)明:初始化互斥鎖之前封豪,必須將其所在的內(nèi)存清零谴轮。如果互斥鎖已初始化,則它會(huì)處于未鎖定狀態(tài)
  • 設(shè)置鎖的屬性
    pthread_mutexattr_init(pthread_mutexattr_t *mattr);//互斥鎖屬性可以由該函數(shù)來(lái)初始化吹埠,然后再調(diào)用其他的函數(shù)來(lái)設(shè)置其屬性
    int pthread_mutexattr_setpshared(pthread_mutexattr_t *mattr, int pshared)
    int pthread_mutexattr_getshared(pthread_mutexattr_t *mattr,int *pshared))//可以指定是該進(jìn)程與其他進(jìn)程的同步還是同一進(jìn)程內(nèi)不同的線程之間的同步第步。可以設(shè)置為PTHREAD_PROCESS_SHARE和PTHREAD_PROCESS_PRIVATE缘琅。默認(rèn)是后者粘都,表示進(jìn)程內(nèi)使用鎖
    init pthread_mutexattr_settype(pthread_mutexattr_t *attr , int type)
    init pthread_mutexattr_gettype(pthread_mutexattr_t *attr , int *type)

互斥鎖的類(lèi)型,有以下幾個(gè)取值空間:
PTHREAD_MUTEX_TIMED_NP,這是缺省值刷袍,也就是普通鎖翩隧。當(dāng)一個(gè)線程加鎖以后,其余請(qǐng)求鎖的線程將形成一個(gè)等待隊(duì)列呻纹,并在解鎖后按優(yōu)先級(jí)獲得鎖鸽心。這種鎖策略保證了資源分配的公平性。
PTHREAD_MUTEX_RECURSIVE_NP居暖,嵌套鎖顽频,允許同一個(gè)線程對(duì)同一個(gè)鎖成功獲得多次,并通過(guò)多次unlock解鎖太闺。如果是不同線程請(qǐng)求糯景,則在加鎖線程解鎖時(shí)重新競(jìng)爭(zhēng)。
PTHREAD_MUTEX_ERRORCHECK_NP省骂,檢錯(cuò)鎖蟀淮,如果同一個(gè)線程請(qǐng)求同一個(gè)鎖,則返回EDEADLK钞澳,否則與PTHREAD_MUTEX_TIMED_NP類(lèi)型動(dòng)作相同怠惶。這樣就保證當(dāng)不允許多次加鎖時(shí)不會(huì)出現(xiàn)最簡(jiǎn)單情況下的死鎖。
PTHREAD_MUTEX_ADAPTIVE_NP轧粟,適應(yīng)鎖策治,動(dòng)作最簡(jiǎn)單的鎖類(lèi)型脓魏,僅等待解鎖后重新競(jìng)爭(zhēng)。

  • 上鎖
    void _int pthread_mutex_lock(pthread_mutex_t *mutex);//無(wú)法獲得鎖時(shí)通惫,睡眠等待茂翔,不會(huì)被信號(hào)中斷
    返回值:0, 成功;其他值履腋,失斏毫恰;EAGAIN遵湖,由于已超出了互斥鎖遞歸鎖定的最大次數(shù)悔政,因此無(wú)法獲取該互斥鎖;EDEADLK:當(dāng)前線程已經(jīng)擁有互斥鎖延旧。
  • 解鎖
    int pthread_mutex_unlock(pthread_mutex_t *mutex);
    函數(shù)說(shuō)明:如果調(diào)用 pthread_mutex_unlock() 時(shí)有多個(gè)線程被 mutex 對(duì)象阻塞卓箫,則互斥鎖變?yōu)榭捎脮r(shí)調(diào)度策略可確定獲取該互斥鎖的線程。對(duì)于 PTHREAD_MUTEX_RECURSIVE 類(lèi)型的互斥鎖垄潮,當(dāng)計(jì)數(shù)達(dá)到零并且調(diào)用線程不再對(duì)該互斥鎖進(jìn)行任何鎖定時(shí)烹卒,該互斥鎖將變?yōu)榭捎?
  • 非阻塞模式的互斥鎖
    int pthread_mutex_trylock(pthread_mutex_t *mutex);
    函數(shù)說(shuō)明:pthread_mutex_lock() 的非阻塞版本。如果 mutex 所引用的互斥對(duì)象當(dāng)前被任何線程(包括當(dāng)前線程)鎖定弯洗,則將立即返回該調(diào)用旅急。否則,該互斥鎖將處于鎖定狀態(tài)牡整,調(diào)用線程是其屬主
  • 互斥鎖的特點(diǎn)

1)互斥鎖的特性藐吮,是一種信號(hào)量,常用來(lái)防止兩個(gè)線程在同一時(shí)刻訪問(wèn)相同的共享資源逃贝。它有以下三個(gè)特性:
唯一性:如果一個(gè)線程鎖定了一個(gè)互斥量谣辞,在它解除鎖定之前,沒(méi)有其他線程可以鎖定這個(gè)互斥量沐扳;
原子性:把一個(gè)互斥量鎖定為一個(gè)原子操作泥从,這意味著操作系統(tǒng)(或pthread函數(shù)庫(kù))保證了如果一個(gè)線程鎖定了一個(gè)互斥量,沒(méi)有其他線程在同一時(shí)間可以成功鎖定這個(gè)互斥量沪摄;
非繁忙等待:如果一個(gè)線程已經(jīng)鎖定了一個(gè)互斥量躯嫉,第二個(gè)線程又試圖去鎖定這個(gè)互斥量,則第二個(gè)線程將被掛起(不占用任何cpu資源)杨拐,直到第一個(gè)線程解除對(duì)這個(gè)互斥量的鎖定為止祈餐,第二個(gè)線程則被喚醒并繼續(xù)執(zhí)行,同時(shí)鎖定這個(gè)互斥量哄陶。
2)互斥鎖的作用域
互斥鎖一般用在線程間帆阳,當(dāng)然可以通過(guò)設(shè)置互斥鎖的屬性讓它在進(jìn)程間使用。

  1. 互斥鎖和信號(hào)量比較
  • 互斥鎖功能上基本與二元信號(hào)量一樣屋吨,但是互斥鎖占用空間比信號(hào)量小蜒谤,運(yùn)行效率比信號(hào)量高山宾。所以,如果要用于線程間的互斥芭逝,優(yōu)先選擇互斥鎖。

上面這種解釋是有問(wèn)題了渊胸,除了開(kāi)銷(xiāo)上的區(qū)別, 我們還應(yīng)該關(guān)注兩者在語(yǔ)義上的區(qū)別:
互斥:是指某一資源同時(shí)只允許一個(gè)訪問(wèn)者對(duì)其進(jìn)行訪問(wèn)旬盯,具有唯一性和排它性。但互斥無(wú)法限制訪問(wèn)者對(duì)資源的訪問(wèn)順序翎猛,即訪問(wèn)是無(wú)序的胖翰。舉個(gè)例子,如果資源被鎖定切厘,另外一個(gè)線程嘗試獲取鎖時(shí)萨咳,并阻塞線程,至于下一次什么時(shí)候線程被喚醒是未可知的疫稿,這個(gè)取決于cpu的調(diào)度培他。所以使用互斥鎖會(huì)出現(xiàn)優(yōu)先級(jí)倒置(prority inversion)的問(wèn)題,高優(yōu)先級(jí)的線程反而被延遲執(zhí)行遗座。
同步:是指在互斥的基礎(chǔ)上(大多數(shù)情況)舀凛,通過(guò)其它機(jī)制實(shí)現(xiàn)訪問(wèn)者對(duì)資源的有序訪問(wèn)。在大多數(shù)情況下途蒋,同步已經(jīng)實(shí)現(xiàn)了互斥猛遍,特別是所有寫(xiě)入資源的情況必定是互斥的。少數(shù)情況是指可以允許多個(gè)訪問(wèn)者同時(shí)訪問(wèn)資源号坡。信號(hào)量一般會(huì)采用解鎖通知等待隊(duì)列中的線程(可以設(shè)置調(diào)度順序懊烤,當(dāng)然等待隊(duì)列的開(kāi)銷(xiāo)需要額外支出的)

  1. 互斥鎖和自旋鎖比較
  • 互斥鎖在無(wú)法得到資源時(shí),內(nèi)核線程會(huì)進(jìn)入睡眠阻塞狀態(tài)宽堆,而自旋鎖處于忙等待狀態(tài)腌紧。因此,如果資源被占用的時(shí)間較長(zhǎng)畜隶,使用互斥鎖較好寄啼,因?yàn)榭勺孋PU調(diào)度去做其它進(jìn)程的工作。
  • 如果被保護(hù)資源需要睡眠的話代箭,那么只能使用互斥鎖或者信號(hào)量墩划,不能使用自旋鎖。而互斥鎖的效率又比信號(hào)量高嗡综,所以這時(shí)候最佳選擇是互斥鎖乙帮。
  • 中斷里面不能使用互斥鎖,因?yàn)榛コ怄i在獲取不到鎖的情況下會(huì)進(jìn)入睡眠极景,而中斷是不能睡眠的

注意察净,為了防止死鎖驾茴,不能在同一個(gè)線程里面兩次申請(qǐng)同樣的鎖,同時(shí)也不推薦在不同的線程里面同時(shí)申請(qǐng)兩個(gè)一樣的鎖氢卡。

2. 自旋鎖在內(nèi)核中的運(yùn)用

內(nèi)核中自旋鎖的運(yùn)行機(jī)制:
  • 單處理器自旋鎖的工作流程是:單處理器中自旋鎖不被啟用锈至,因?yàn)槭褂米孕i的中斷執(zhí)行路徑一旦被嵌套可能會(huì)造成永久等待,同步途徑是關(guān)閉內(nèi)核搶占->運(yùn)行臨界區(qū)代碼->開(kāi)啟內(nèi)核搶占译秦。更加安全的單處理器自旋鎖工作流程是:保存IF寄存器->關(guān)閉當(dāng)前CPU中斷->關(guān)閉內(nèi)核搶占->運(yùn)行臨界區(qū)代碼->開(kāi)啟內(nèi)核搶占->開(kāi)啟當(dāng)前CPU中斷->恢復(fù)IF寄存器峡捡。
  • 多處理器自旋鎖的工作流程是:關(guān)閉內(nèi)核搶占->(忙等待->)獲取自旋鎖->運(yùn)行臨界區(qū)代碼->釋放自旋鎖->開(kāi)啟內(nèi)核搶占。更加安全的多處理器自旋鎖工作流程是:保存IF寄存器->關(guān)閉當(dāng)前CPU中斷->關(guān)閉內(nèi)核搶占->(忙等待->)獲取自旋鎖->運(yùn)行臨界區(qū)代碼->釋放自旋鎖->開(kāi)啟內(nèi)核搶占->開(kāi)啟當(dāng)前CPU中斷->恢復(fù)IF寄存器筑悴。
自旋鎖的實(shí)現(xiàn)和特點(diǎn)
//CAS操作在cpu指令集中可以是原子性的
int CompareAndExchange(int *ptr, int old, int new){
    int actual = *ptr;
    if (actual == old)
    *ptr = new;
    return actual;
}
void lock(lock_t *lock) {
     while (CompareAndExchange(&lock->flag, 0, 1) == 1); // spin
}
void unlock(lock_t *lock) {
     lock->flag = 0;
}

這個(gè)實(shí)現(xiàn)是借助cpu的原子指令CAS實(shí)現(xiàn)的们拙,后面會(huì)介紹原子操作

自旋鎖是采用忙等的狀態(tài)獲取鎖,所以會(huì)一直占用cpu資源阁吝,但是允許不關(guān)閉中斷的情況下砚婆,是可以被其他內(nèi)核執(zhí)行路徑搶占的(中斷嵌套的情況下,注意嵌套的中斷不能申請(qǐng)同一個(gè)鎖突勇,這樣會(huì)造成死等)装盯。同時(shí)因?yàn)榫€程對(duì)cpu一直保持占用狀態(tài),所以對(duì)小資源加鎖效率比較高甲馋,不需要做任何的線程切換验夯,一般情況下如果加鎖資源的運(yùn)行延遲小于線程或者進(jìn)程切換的時(shí)延則推薦使用自旋鎖。如果需要等待耗時(shí)操作摔刁,則建議放棄cpu挥转,采用信號(hào)量或者互斥鎖

3. 原子操作

在介紹原子操作之前需要介紹幾個(gè)概念
image.png
  • 內(nèi)存屏障
  • 編譯優(yōu)化

匯編級(jí)原子操作

最新的處理器能自動(dòng)保證單處理器對(duì)同一個(gè)緩存行里進(jìn)行16/32/64位的操作是原子的,但是復(fù)雜的內(nèi)存操作處理器是不能自動(dòng)保證其原子性的共屈,比如跨總線寬度绑谣、跨多個(gè)緩存行和跨頁(yè)表的訪問(wèn)。但是拗引,處理器提供總線鎖定和緩存鎖定兩個(gè)機(jī)制來(lái)保證復(fù)雜內(nèi)存操作的原子性借宵。如下圖所示就是采用總線鎖定的方式進(jìn)行原子操作:
使用匯編鎖定的方式將三條指令合并成一條指令

上圖指令可以實(shí)現(xiàn)加操作的原子性,但是這種總線鎖不能濫用矾削,在沒(méi)有共享同步問(wèn)題的時(shí)候壤玫,這會(huì)阻止cpu并行計(jì)算的優(yōu)化,甚至?xí)枞鹀pu對(duì)其他內(nèi)存的訪問(wèn)哼凯,導(dǎo)致效率的下降欲间。所以除此之外我們可以使用緩存鎖來(lái)執(zhí)行復(fù)雜的原子操作。

使用緩存鎖保證原子性
第二個(gè)機(jī)制是通過(guò)緩存鎖定來(lái)保證原子性断部。在同一時(shí)刻猎贴,我們只需保證對(duì)某個(gè)內(nèi)存地址的操作是原子性即可,但總線鎖定把CPU和內(nèi)存之間的通信鎖住了,這使得鎖定期間她渴,其他處理器不能操作其他內(nèi)存地址的數(shù)據(jù)达址,所以總線鎖定的開(kāi)銷(xiāo)比較大,目前處理器在某些場(chǎng)合下使用緩存鎖定代替總線鎖定來(lái)進(jìn)行優(yōu)化趁耗。

頻繁使用的內(nèi)存會(huì)緩存在處理器的L1沉唠、L2和L3高速緩存里,那么原子操作就可以直接在處理器內(nèi)部緩存中進(jìn)行苛败,并不需要聲明總線鎖满葛,在Pentium 6和目前的處理器中可以使用“緩存鎖定”的方式來(lái)實(shí)現(xiàn)復(fù)雜的原子性。所謂“緩存鎖定”是指內(nèi)存區(qū)域如果被緩存在處理器的緩存行中著拭,并且在Lock操作期間被鎖定纱扭,那么當(dāng)它執(zhí)行鎖操作回寫(xiě)到內(nèi)存時(shí)牍帚,處理器不在總線上聲言LOCK#信號(hào)儡遮,而是修改內(nèi)部的內(nèi)存地址,并允許它的緩存一致性機(jī)制來(lái)保證操作的原子性暗赶,因?yàn)榫彺嬉恢滦詸C(jī)制會(huì)阻止同時(shí)修改由兩個(gè)以上處理器緩存的內(nèi)存區(qū)域數(shù)據(jù)鄙币,當(dāng)其他處理器回寫(xiě)已被鎖定的緩存行的數(shù)據(jù)時(shí),會(huì)使緩存行無(wú)效蹂随,在如圖2-3所示的例子中十嘿,當(dāng)CPU1修改緩存行中的i時(shí)使用了緩存鎖定,那么CPU2就不能同時(shí)緩存i的緩存行岳锁。
但是有兩種情況下處理器不會(huì)使用緩存鎖定绩衷。

第一種情況是:當(dāng)操作的數(shù)據(jù)不能被緩存在處理器內(nèi)部,或操作的數(shù)據(jù)跨多個(gè)緩存行(cache line)時(shí)激率,則處理器會(huì)調(diào)用總線鎖定咳燕。
第二種情況是:有些處理器不支持緩存鎖定。對(duì)于Intel 486和Pentium處理器乒躺,就算鎖定的內(nèi)存區(qū)域在處理器的緩存行中也會(huì)調(diào)用總線鎖定招盲。

未完待續(xù)。嘉冒。曹货。。

references:

https://www.cnblogs.com/alinh/p/6905221.html
https://blog.csdn.net/mcgrady_tracy/article/details/34829019
https://leetcode.com/discuss/interview-question/operating-system/125169/Mutex-vs-Semaphore
https://blog.csdn.net/zxx901221/article/details/83033998
https://leetcode.com/discuss/interview-question/operating-system/134290/Implement-your-own-spinlock

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末讳推,一起剝皮案震驚了整個(gè)濱河市顶籽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌银觅,老刑警劉巖蜕衡,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡慨仿,警方通過(guò)查閱死者的電腦和手機(jī)久脯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)镰吆,“玉大人帘撰,你說(shuō)我怎么就攤上這事⊥蛎螅” “怎么了摧找?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)牢硅。 經(jīng)常有香客問(wèn)我蹬耘,道長(zhǎng),這世上最難降的妖魔是什么减余? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任综苔,我火速辦了婚禮,結(jié)果婚禮上位岔,老公的妹妹穿的比我還像新娘如筛。我一直安慰自己,他們只是感情好抒抬,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布杨刨。 她就那樣靜靜地躺著,像睡著了一般擦剑。 火紅的嫁衣襯著肌膚如雪妖胀。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天惠勒,我揣著相機(jī)與錄音赚抡,去河邊找鬼。 笑死捉撮,一個(gè)胖子當(dāng)著我的面吹牛怕品,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播巾遭,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼肉康,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了灼舍?” 一聲冷哼從身側(cè)響起吼和,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎骑素,沒(méi)想到半個(gè)月后炫乓,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年末捣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了侠姑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡箩做,死狀恐怖莽红,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情邦邦,我是刑警寧澤安吁,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站燃辖,受9級(jí)特大地震影響鬼店,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜黔龟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一妇智、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧捌锭,春花似錦俘陷、人聲如沸罗捎。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)桨菜。三九已至豁状,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間倒得,已是汗流浹背泻红。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留美莫,地道東北人苛谷。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓碉克,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親缠劝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 在上篇中,我們已經(jīng)討論過(guò)如何去實(shí)現(xiàn)一個(gè) Map 了耙旦,并且也討論了諸多優(yōu)化點(diǎn)脱羡。在下篇中,我們將繼續(xù)討論如何實(shí)現(xiàn)一個(gè)線...
    一縷殤流化隱半邊冰霜閱讀 7,624評(píng)論 5 41
  • 1 臨界區(qū) 1.1簡(jiǎn)介 在早期計(jì)算機(jī)系統(tǒng)中,只有一個(gè)任務(wù)進(jìn)程在執(zhí)行锉罐,并不存在資源的共享與競(jìng)爭(zhēng)帆竹。隨著技術(shù)和需求的飛速...
    Fly晴天里Fly閱讀 9,034評(píng)論 2 13
  • OSSpinLock OSSpinLock 不再安全,主要原因發(fā)生在低優(yōu)先級(jí)線程拿到鎖時(shí)脓规,高優(yōu)先級(jí)線程進(jìn)入忙等(b...
    GAME666閱讀 1,286評(píng)論 0 0
  • Q:為什么出現(xiàn)多線程馆揉? A:為了實(shí)現(xiàn)同時(shí)干多件事的需求(并發(fā)),同時(shí)進(jìn)行著下載和頁(yè)面UI刷新抖拦。對(duì)于處理器升酣,為每個(gè)線...
    幸福相依閱讀 1,582評(píng)論 0 2
  • 交朋友 有很多因素 首先 三觀一致 不一致的走著走著就散了 然后尊重 我可以忍你一時(shí)間 忍不了一世 還有真誠(chéng) 互相...
    sunandshade閱讀 199評(píng)論 0 0