Java并發(fā)編程之鎖機(jī)制之(ReentrantLock)重入鎖

小兔子.jpg

最近在忙公司的項(xiàng)目疲恢,現(xiàn)在終于有時(shí)間來(lái)寫博客啦~開心開心

前言

通過(guò)前面的文章,我們已經(jīng)了解了AQS(AbstractQueuedSynchronizer)內(nèi)部的實(shí)現(xiàn)與基本原理。現(xiàn)在我們來(lái)了解一下,Java中為我們提供的Lock機(jī)制下的鎖實(shí)現(xiàn)--ReentrantLock(重入鎖),閱讀該篇文章之前妻顶,希望你已閱讀以下文章。

ReentrantLock基本介紹

ReentrantLock是一種可重入互斥鎖蜒车,它具有與使用synchronized方法和語(yǔ)句所訪問(wèn)的隱式監(jiān)視器鎖相同的一些基本行為和語(yǔ)義讳嘱,但功能更強(qiáng)大。

ReentrantLock 將由最近成功獲得鎖酿愧,并且還沒(méi)有釋放該鎖的線程所擁有沥潭。當(dāng)鎖沒(méi)有被另一個(gè)線程所擁有時(shí),調(diào)用 lock 的線程將成功獲取該鎖并返回嬉挡。如果當(dāng)前線程已經(jīng)擁有該鎖钝鸽,此方法將立即返回∨痈郑可以使用isHeldByCurrentThread()getHoldCount()方法來(lái)檢查此情況是否發(fā)生拔恰。

此類的構(gòu)造方法接受一個(gè)可選的公平參數(shù)。當(dāng)設(shè)置為 true 時(shí)(也是當(dāng)前ReentrantLock為公平鎖的情況)基括,在多個(gè)線程的爭(zhēng)用下颜懊,這些鎖傾向于將訪問(wèn)權(quán)授予等待時(shí)間最長(zhǎng)的線程。否則此鎖將無(wú)法保證任何特定訪問(wèn)順序风皿。與采用默認(rèn)設(shè)置(使用不公平鎖)相比河爹,使用公平鎖的程序在許多線程訪問(wèn)時(shí)表現(xiàn)為很低的總體吞吐量(即速度很慢,常常極其慢)桐款,但是在獲得鎖和保證鎖分配的均衡性時(shí)差異較小咸这。不過(guò)要注意的是,公平鎖不能保證線程調(diào)度的公平性魔眨。因此媳维,使用公平鎖的眾多線程中的一員可能獲得多倍的成功機(jī)會(huì)酿雪,這種情況發(fā)生在其他活動(dòng)線程沒(méi)有被處理并且目前并未持有鎖時(shí)。還要注意的是侄刽,未定時(shí)的 tryLock 方法并沒(méi)有使用公平設(shè)置执虹。因?yàn)榧词蛊渌€程正在等待,只要該鎖是可用的唠梨,此方法就可以獲得成功。

ReentrantLock 類基本結(jié)構(gòu)

通過(guò)上文的簡(jiǎn)單介紹后侥啤,我相信很多小伙伴還是一臉懵逼当叭,只知道上文我們提到了ReentrantLocksynchronized相比有相同的語(yǔ)義,同時(shí)其內(nèi)部分為了公平鎖非公平鎖兩種鎖的類型盖灸,且該鎖是支持重進(jìn)入的蚁鳖。那么為了方便大家理解這些知識(shí)點(diǎn),我們先從其類的基本結(jié)構(gòu)講起赁炎。具體類結(jié)構(gòu)如下圖所示:

ReentrantLock.png

從上圖中我們可以看出醉箕,在ReentrantLock類中,定義了三個(gè)靜態(tài)內(nèi)部類徙垫,Sync讥裤、FairSync(公平鎖)NonfairSync(非公平鎖)姻报。其中Sync繼承了AQS(AbstractQueuedSynchronizer)己英,而FairSyncNonfairSync又分別繼承了Sync。關(guān)于ReentrantLock基本類結(jié)構(gòu)如下所示:

public class ReentrantLock implements Lock, java.io.Serializable {
    private final Sync sync;

    //默認(rèn)無(wú)參構(gòu)造函數(shù)吴旋,默認(rèn)為非公平鎖
    public ReentrantLock() {
        sync = new NonfairSync();
    }
    //帶參數(shù)的構(gòu)造函數(shù)损肛,用戶自己來(lái)決定是公平鎖還是非公平鎖
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }
    //抽象基類繼承AQS,公平鎖與非公平鎖繼承該類荣瑟,并分別實(shí)現(xiàn)其lock()方法
    abstract static class Sync extends AbstractQueuedSynchronizer {
        abstract void lock();
        //省略部分代碼..
    }
    
    //非公平鎖實(shí)現(xiàn)
    static final class NonfairSync extends Sync {...}
    
    //公平鎖實(shí)現(xiàn)
    static final class FairSync extends Sync {....}
   
    //鎖實(shí)現(xiàn)治拿,根據(jù)具體子類實(shí)現(xiàn)調(diào)用
    public void lock() {
        sync.lock();
    }
    //響應(yīng)中斷的獲取鎖
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }
    //嘗試獲取鎖,默認(rèn)采用非公平鎖方法實(shí)現(xiàn)
    public boolean tryLock() {
        return sync.nonfairTryAcquire(1);
    }
    //超時(shí)獲取鎖
    public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }
    //釋放鎖
    public void unlock() {
        sync.release(1);
    }
    //創(chuàng)建鎖條件(從Condetion來(lái)理解笆焰,就是創(chuàng)建等待隊(duì)列)
    public Condition newCondition() {
        return sync.newCondition();
    }
    //省略部分代碼....
}

這里為了方便大家理解ReentrantLock類的整體結(jié)構(gòu)劫谅,我省略了一些代碼及重新排列了一些代碼的順序。

從代碼中我們可以看出仙辟。整個(gè)ReentrantLock類的實(shí)現(xiàn)其實(shí)都是交給了其內(nèi)部FairSyncNonfairSync兩個(gè)類同波。在ReentrantLock類中有兩個(gè)構(gòu)造函數(shù)未檩,其中不帶參數(shù)的構(gòu)造函數(shù)中默認(rèn)使用的NonfairSync(非公平鎖)。另一個(gè)帶參數(shù)的構(gòu)造函數(shù),用戶自己來(lái)決定是FairSync(公平鎖)還是非公平鎖晴楔。

重進(jìn)入實(shí)現(xiàn)

在上文中,我們提到了ReentrantLock是支持重進(jìn)入的幔翰,那什么是重進(jìn)入呢贡定?重進(jìn)入是指任意線程在獲取到鎖之后能夠再次獲取該鎖旋炒,而不會(huì)被鎖阻塞铣除。那接下來(lái)我們看看這個(gè)例子敲长,如下所示:

class ReentrantLockDemo {
    private static final ReentrantLock lock = new ReentrantLock();
    
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                methodA();
            }
        });
        thread.start();
    }
    
    public static void methodA() {
        lock.lock();
        try {
            System.out.println("我已經(jīng)進(jìn)入methodA方法了");
            methodB();//方法A中繼續(xù)調(diào)用方法B
        } finally {
            lock.unlock();
        }
    }

    public static void methodB() {
        lock.lock();
        try {
            System.out.println("我已經(jīng)進(jìn)入methodB方法了");
        } finally {
            lock.unlock();
        }
    }
}
//輸出結(jié)果
我已經(jīng)進(jìn)入methodA方法了
我已經(jīng)進(jìn)入methodB方法了

在上述代碼中我們聲明了一個(gè)線程調(diào)用methodA()方法杠茬。同時(shí)在該方法內(nèi)部我們又調(diào)用了methodB()方法。從實(shí)際的代碼運(yùn)行結(jié)果來(lái)看礁击,當(dāng)前線程進(jìn)入方法A之后盐杂。在方法B中再次調(diào)用lock.lock();時(shí),該線程并沒(méi)有被阻塞哆窿。也就是說(shuō)ReentrantLock是支持重進(jìn)入的链烈。那下面我們就一起來(lái)看看其內(nèi)部的實(shí)現(xiàn)原理。

因?yàn)?code>ReenTrantLock將具體實(shí)現(xiàn)交給了NonfairSync(非公平鎖)FairSync(公平鎖)挚躯。同時(shí)又因?yàn)樯鲜鎏岬降膬蓚€(gè)鎖强衡,關(guān)于重進(jìn)入的實(shí)現(xiàn)又非常相似。所以這里將采用NonfairSync(非公平鎖)的重進(jìn)入的實(shí)現(xiàn)码荔,來(lái)進(jìn)行分析漩勤。希望讀者朋友們閱讀到這里的時(shí)候需要注意,不是我懶哦缩搅,是真的很相似哦越败。

好了下面我們來(lái)看代碼。關(guān)于NonfairSync代碼如下所示:

static final class NonfairSync extends Sync {
        final void lock() {
            if (compareAndSetState(0, 1))////直接獲取同步狀態(tài)成功硼瓣,那么就不再走嘗試獲取鎖的過(guò)程
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

當(dāng)我們調(diào)用lock()方法時(shí)究飞,通過(guò)CAS操作將AQS中的state的狀態(tài)設(shè)置為1,如果成功堂鲤,那么表示獲取同步狀態(tài)成功亿傅。那么會(huì)接著調(diào)用setExclusiveOwnerThread(Thread thread)方法來(lái)設(shè)置當(dāng)前占有鎖的線程。如果失敗瘟栖,則調(diào)用acquire(int arg)方法來(lái)獲取同步狀態(tài)(該方法是屬于AQS中的獨(dú)占式獲取同步狀態(tài)的方法葵擎,對(duì)該方法不熟悉的小伙伴,建議閱讀 Java并發(fā)編程之鎖機(jī)制之AQS(AbstractQueuedSynchronizer))慢宗。而該方法內(nèi)部會(huì)調(diào)用tryAcquire(int acquires)來(lái)嘗試獲取同步狀態(tài)坪蚁。通過(guò)觀察奔穿,我們發(fā)現(xiàn)最終會(huì)調(diào)用Sync類中的nonfairTryAcquire(int acquires)方法。我們繼續(xù)跟蹤敏晤。

    final boolean nonfairTryAcquire(int acquires) {
            //獲取當(dāng)前線程
            final Thread current = Thread.currentThread();
            int c = getState();
            //(1)判斷同步狀態(tài)贱田,如果未設(shè)置,則設(shè)置同步狀態(tài)
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            //(2)如果當(dāng)前線程已經(jīng)獲取了同步狀態(tài)嘴脾,則增加同步狀態(tài)的值男摧。
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

從代碼上來(lái)看,該方法主要走兩個(gè)步驟译打,具體如下所示:

  • (1)先判斷同步狀態(tài)耗拓, 如果未曾設(shè)置,則設(shè)置同步狀態(tài)奏司,并設(shè)置當(dāng)前占有鎖的線程乔询。
  • (2)判斷是否是同一線程,如果當(dāng)前線程已經(jīng)獲取了同步狀態(tài)(也就是獲取了鎖)韵洋,那么增加同步狀態(tài)的值竿刁。

也就是說(shuō),如果同一個(gè)鎖獲取了鎖N(N為正整數(shù))次搪缨,那么對(duì)應(yīng)的同步狀態(tài)(state)也就等于N食拜。那么接下來(lái)的問(wèn)題來(lái)了,如果當(dāng)前線程重復(fù)N次獲取了鎖副编,那么該線程是否需要釋放鎖N次呢负甸?答案當(dāng)然是必須的。當(dāng)我們調(diào)用ReenTrantLock的unlock()方法來(lái)釋放同步狀態(tài)(也就是釋放鎖)時(shí)痹届,內(nèi)部會(huì)調(diào)用sync.release(1);呻待。最終會(huì)調(diào)用Sync類的tryRelease(int releases)方法。具體代碼如下所示:

  protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

從代碼中队腐,我們可以知道带污,每調(diào)用一次unlock()方法會(huì)將當(dāng)前同步狀態(tài)減一。也就是說(shuō)如果當(dāng)前線程獲取了鎖N次香到,那么獲取鎖的相應(yīng)線程也需要調(diào)用unlock()方法N次鱼冀。這也是為什么我們?cè)谥暗闹厝腈i例子中,為什么methodB方法中也要釋放鎖的原因悠就。

非公平鎖

在ReentrantLock中有著非公平鎖公平鎖的概念千绪,這里我先簡(jiǎn)單的介紹一下公平這兩個(gè)字的含義。這里的公平是指線程獲取鎖的順序梗脾。也就是說(shuō)鎖的獲取順序是按照當(dāng)前線程請(qǐng)求的絕對(duì)時(shí)間順序荸型,當(dāng)然前提條件下是該線程獲取鎖成功

那么接下來(lái)炸茧,我們來(lái)分析在ReentrantLock中的非公平鎖的具體實(shí)現(xiàn)瑞妇。

這里需要大家具備AQS(AbstractQueuedSynchronizer)類的相關(guān)知識(shí)稿静。如果大家不熟悉這塊的知識(shí)。建議大家閱讀 Java并發(fā)編程之鎖機(jī)制之AQS(AbstractQueuedSynchronizer)辕狰。

    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        final void lock() {
            if (compareAndSetState(0, 1))//直接獲取同步狀態(tài)成功改备,那么就不再走嘗試獲取鎖的過(guò)程
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }
        //省略部分代碼...
    }

當(dāng)在ReentrantLock在非公平鎖的模式下,去調(diào)用lock()方法蔓倍。那么接下來(lái)最終會(huì)走AQS(AbstractQueuedSynchronizer)下的acquire(int arg)(獨(dú)占式的獲取同步狀態(tài))悬钳,也就是如下代碼:

  public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

那么結(jié)合之前我們所講的AQS知識(shí),在多個(gè)線程在獨(dú)占式請(qǐng)求共享狀態(tài)下(也就是請(qǐng)求鎖)的情況下偶翅,在AQS中的同步隊(duì)列中的線程節(jié)點(diǎn)情況如下圖所示:

aqs同步隊(duì)列中線程節(jié)點(diǎn)的情況.png

那么我們?cè)囅胍环N情況默勾,當(dāng)Nod1中的線程執(zhí)行完相應(yīng)任務(wù)后,釋放鎖后聚谁。這個(gè)時(shí)候本來(lái)該喚醒當(dāng)前線程節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn),也就是Node2中的線程母剥。這個(gè)時(shí)候突然另一線程突然來(lái)獲取線程(這里我們用節(jié)點(diǎn)Node5來(lái)表示)。具體情況如下圖所示:

突然線程請(qǐng)求鎖的情況.png

那么根據(jù)AQS中獨(dú)占式獲取同步狀態(tài)的邏輯形导。只要Node5對(duì)應(yīng)的線程獲取同步狀態(tài)成功媳搪。那么就會(huì)出現(xiàn)下面的這種情況,具體情況如下圖所示:

線程搶占后最終的情況.png

從上圖中我們可以看出骤宣,由于Node5對(duì)象的線程搶占了獲取同步狀態(tài)(獲取鎖)的機(jī)會(huì),本身應(yīng)該被喚醒的Node2線程節(jié)點(diǎn)序愚。因?yàn)楂@取同步狀態(tài)失敗憔披。所以只有再次的陷入阻塞。那么綜上爸吮。我們可以知道芬膝。非公平鎖獲取同步狀態(tài)(獲取鎖)時(shí)不會(huì)考慮同步隊(duì)列中中等待的問(wèn)題。會(huì)直接嘗試獲取鎖形娇。也就是會(huì)存在后申請(qǐng)锰霜,但是會(huì)先獲得同步狀態(tài)(獲取鎖)的情況。

公平鎖

理解了非公平鎖桐早,再來(lái)理解公平鎖就非常簡(jiǎn)單了癣缅。下面我們來(lái)看一下公平鎖與非公平鎖的加鎖的源碼:

非公平鎖與公平鎖源碼區(qū)別.png

從源碼我們可以看出,非公平鎖與公平鎖之間的代碼唯一區(qū)別就是多了一個(gè)判斷條件!hasQueuedPredecessors()(圖中紅框所示)哄酝。那我們查看其源碼(該代碼在AQS中友存,強(qiáng)烈建議閱讀 Java并發(fā)編程之鎖機(jī)制之AQS(AbstractQueuedSynchronizer)

    public final boolean hasQueuedPredecessors() {
        Node t = tail;
        Node h = head;
        Node s;
        return h != t &&
            ((s = h.next) == null || s.thread != Thread.currentThread());
    }

代碼理解理解起來(lái)非常簡(jiǎn)單,就是判斷當(dāng)前當(dāng)前head節(jié)點(diǎn)的next節(jié)點(diǎn)是不是當(dāng)前請(qǐng)求同步狀態(tài)(請(qǐng)求鎖)的線程陶衅。也就是語(yǔ)句
((s = h.next) == null || s.thread != Thread.currentThread()屡立。那么接下來(lái)結(jié)合AQS中的同步隊(duì)列我們可以得到下圖:

公平鎖搶占情況.png

那么綜上我們可以得出,公平鎖保證了線程請(qǐng)求的同步狀態(tài)(請(qǐng)求鎖)的順序搀军。不會(huì)出現(xiàn)另一個(gè)線程搶占的情況膨俐。

最后

該文章參考以下圖書勇皇,站在巨人的肩膀上》俅蹋可以看得更遠(yuǎn)敛摘。

  • 《Java并發(fā)編程的藝術(shù)》

推薦閱讀

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市檩坚,隨后出現(xiàn)的幾起案子着撩,更是在濱河造成了極大的恐慌,老刑警劉巖匾委,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拖叙,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡赂乐,警方通過(guò)查閱死者的電腦和手機(jī)薯鳍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)挨措,“玉大人挖滤,你說(shuō)我怎么就攤上這事∏骋郏” “怎么了斩松?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)觉既。 經(jīng)常有香客問(wèn)我惧盹,道長(zhǎng),這世上最難降的妖魔是什么瞪讼? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任钧椰,我火速辦了婚禮,結(jié)果婚禮上符欠,老公的妹妹穿的比我還像新娘嫡霞。我一直安慰自己,他們只是感情好希柿,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布诊沪。 她就那樣靜靜地躺著,像睡著了一般曾撤。 火紅的嫁衣襯著肌膚如雪娄徊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天盾戴,我揣著相機(jī)與錄音寄锐,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛橄仆,可吹牛的內(nèi)容都是我干的剩膘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼盆顾,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼怠褐!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起您宪,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤奈懒,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后宪巨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體磷杏,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年捏卓,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了极祸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡怠晴,死狀恐怖遥金,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蒜田,我是刑警寧澤稿械,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站冲粤,受9級(jí)特大地震影響美莫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜色解,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望餐茵。 院中可真熱鬧科阎,春花似錦、人聲如沸忿族。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)道批。三九已至错英,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間隆豹,已是汗流浹背椭岩。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人判哥。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓献雅,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親塌计。 傳聞我的和親對(duì)象是個(gè)殘疾皇子挺身,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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

  • 我與老局長(zhǎng)林鈞岱(上) 林鈞岱,1983年4月至1986年4月?lián)文暇┦泄簿志珠L(zhǎng)锌仅。 ...
    俞家巷閱讀 10,657評(píng)論 0 3
  • 最近微信的小程序也是火的的不行章钾,畢竟那潛在的8億用戶影響還是巨大的。想起了小程序剛開始時(shí)傳爆朋友圈的那張長(zhǎng)截圖热芹。哈...
    violinlin閱讀 1,606評(píng)論 1 3
  • 我出生于農(nóng)村贱傀,家里本不富裕。讀初三那年就在中考前兩個(gè)月家里出了意想不到的事情(這事我埋在心里再也不想提起)剿吻,使...
    潘思敏閱讀 174評(píng)論 0 1
  • “關(guān)系力塔樓” 第6組3張便簽窍箍,共計(jì)18張便簽。 【原文】 別獨(dú)自用餐 第113頁(yè)--114頁(yè) 深度攀談 【I便...
    迷猴桃sally閱讀 213評(píng)論 0 0