Python并發(fā)總結(jié)筆記

最近做項(xiàng)目的時(shí)候,自己寫了個(gè)腳本用來測試漏洞信息,但是因?yàn)殚_始寫的是單線程的日川,所以效率比較低遭庶,想要優(yōu)化一下腳本,所以總結(jié)一下并發(fā)的相關(guān)知識(shí)狞玛。

無線程版本

首先創(chuàng)建一個(gè)簡單的程序用來顯示效果:

import time
port_list = []
for i in range(10):
    port_list.append(i)
for i in port_list:
    print(i)
    time.sleep(1)

向list中添加1-10类浪,并且等待一秒喳逛,用時(shí)間來判斷效率有沒有提升邮偎。

可以看到單線程下用了10秒管跺。

加入threading

threading庫可用來在單獨(dú)的線程中執(zhí)行任意Python可調(diào)用對(duì)象,我們首先使用threading模塊的Thread類來創(chuàng)建一個(gè)線程禾进,先要?jiǎng)?chuàng)建一個(gè)實(shí)例豁跑,在傳給它一個(gè)函數(shù),最后開啟線程泻云,代碼如下:

import time 
import threading

port_list = []
threads = []

def printf(i):
    print(i)
    time.sleep(1)
def main():
    for i in range(10):
        port_list.append(i)
    for i in port_list:
        t = threading.Thread(target=printf,args=(i,))
        threads.append(t)
    for t in threads:
        t.start()
        while True:
            if(len(threading.enumerate())<100):
                break

if __name__ == '__main__':
    main()

這里我們將輸出寫成了一個(gè)函數(shù)艇拍,將需要輸出的值通過傳參的方式傳給函數(shù),然后通過while循環(huán)和threading.enumerate()來控制線程數(shù)宠纯。
我們看到在建立了10個(gè)線程的情況下卸夕,代碼運(yùn)行僅需要1秒左右。


這里在漏斗社區(qū)發(fā)的文章可以看到婆瓜,文章還對(duì)利用pop方法傳參和join方法對(duì)線程使用for循環(huán)控制進(jìn)行了優(yōu)化快集。

Lock

如果多個(gè)線程訪問同一個(gè)資源,就可能產(chǎn)生無法預(yù)期的效果廉白。

多線程和多進(jìn)程最大的不同在于个初,多進(jìn)程中,同一個(gè)變量猴蹂,各自有一份拷貝存在于每個(gè)進(jìn)程中院溺,互不影響,而多線程中晕讲,所有變量都由所有線程共享覆获,所以,任何一個(gè)變量都可以被任何一個(gè)線程修改瓢省,因此弄息,線程之間共享數(shù)據(jù)最大的危險(xiǎn)在于多個(gè)線程同時(shí)改一個(gè)變量,把內(nèi)容給改亂了勤婚。

我們引用廖雪峰中的代碼看一下效果:

import time, threading

# 假定這是你的銀行存款:
balance = 0

def change_it(n):
    # 先存后取摹量,結(jié)果應(yīng)該為0:
    global balance
    balance = balance + n
    balance = balance - n

def run_thread(n):
    for i in range(100000):
        change_it(n)

t1 = threading.Thread(target=run_thread, args=(5,))
t2 = threading.Thread(target=run_thread, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
print(balance)

我們定義了一個(gè)共享變量balance,初始值為0馒胆,并且啟動(dòng)兩個(gè)線程缨称,先存后取,理論上結(jié)果應(yīng)該為0祝迂,但是睦尽,由于線程的調(diào)度是由操作系統(tǒng)決定的,當(dāng)t1型雳、t2交替執(zhí)行時(shí)当凡,只要循環(huán)次數(shù)足夠多山害,balance的結(jié)果就不一定是0了。



這是由于高級(jí)語言的一條語句在CPU執(zhí)行時(shí)是若干條語句沿量,即使一個(gè)簡單的計(jì)算:

balance = balance + n

也分兩步:

  • 計(jì)算balance + n浪慌,存入臨時(shí)變量中;
  • 將臨時(shí)變量的值賦給balance朴则。
    也就是可以看成:
x = balance + n
balance = x

由于x是局部變量权纤,兩個(gè)線程各自都有自己的x,當(dāng)代碼正常執(zhí)行時(shí):

初始值 balance = 0

t1: x1 = balance + 5 # x1 = 0 + 5 = 5
t1: balance = x1     # balance = 5
t1: x1 = balance - 5 # x1 = 5 - 5 = 0
t1: balance = x1     # balance = 0

t2: x2 = balance + 8 # x2 = 0 + 8 = 8
t2: balance = x2     # balance = 8
t2: x2 = balance - 8 # x2 = 8 - 8 = 0
t2: balance = x2     # balance = 0

結(jié)果 balance = 0

但是t1和t2是交替運(yùn)行的乌妒,如果操作系統(tǒng)以下面的順序執(zhí)行t1汹想、t2:

初始值 balance = 0

t1: x1 = balance + 5  # x1 = 0 + 5 = 5

t2: x2 = balance + 8  # x2 = 0 + 8 = 8
t2: balance = x2      # balance = 8

t1: balance = x1      # balance = 5
t1: x1 = balance - 5  # x1 = 5 - 5 = 0
t1: balance = x1      # balance = 0

t2: x2 = balance - 8  # x2 = 0 - 8 = -8
t2: balance = x2   # balance = -8

結(jié)果 balance = -8

是因?yàn)樾薷腷alance需要多條語句,而執(zhí)行這幾條語句時(shí)撤蚊,線程可能中斷欧宜,從而導(dǎo)致多個(gè)線程把同一個(gè)對(duì)象的內(nèi)容改亂了。所以拴魄,我們必須確保一個(gè)線程在修改balance的時(shí)候,別的線程一定不能改席镀。因此要加入鎖的機(jī)制來防止這種事情的發(fā)生匹中。

import time, threading

# 假定這是你的銀行存款:
balance = 0
lock = threading.Lock()
def change_it(n):
    # 先存后取,結(jié)果應(yīng)該為0:
    global balance
    balance = balance + n
    balance = balance - n

def run_thread(n):
    for i in range(100000):
        # 先要獲取鎖:
        lock.acquire()
        try:
            # 放心地改吧:
            change_it(n)
        finally:
            # 改完了一定要釋放鎖:
            lock.release()

t1 = threading.Thread(target=run_thread, args=(5,))
t2 = threading.Thread(target=run_thread, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
print(balance)

這次就不會(huì)有之前的問題發(fā)生:


當(dāng)多個(gè)線程同時(shí)執(zhí)行l(wèi)ock.acquire()時(shí)豪诲,只有一個(gè)線程能成功地獲取鎖顶捷,然后繼續(xù)執(zhí)行代碼,其他線程就繼續(xù)等待直到獲得鎖為止屎篱。
獲得鎖的線程用完后一定要釋放鎖服赎,否則那些苦苦等待鎖的線程將永遠(yuǎn)等待下去,成為死線程交播。所以我們用try...finally來確保鎖一定會(huì)被釋放重虑。
鎖的好處就是確保了某段關(guān)鍵代碼只能由一個(gè)線程從頭到尾完整地執(zhí)行,壞處當(dāng)然也很多秦士,首先是阻止了多線程并發(fā)執(zhí)行缺厉,包含鎖的某段代碼實(shí)際上只能以單線程模式執(zhí)行,效率就大大地下降了隧土。其次提针,由于可以存在多個(gè)鎖,不同的線程持有不同的鎖曹傀,并試圖獲取對(duì)方持有的鎖時(shí)辐脖,可能會(huì)造成死鎖,導(dǎo)致多個(gè)線程全部掛起皆愉,既不能執(zhí)行嗜价,也無法結(jié)束艇抠,只能靠操作系統(tǒng)強(qiáng)制終止。

避免死鎖的一種解決方案就是給程序中的每個(gè)鎖分配一個(gè)唯一的數(shù)字編號(hào)炭剪,并且獲得多個(gè)鎖的時(shí)候只需按照編號(hào)升序來獲取练链。可以利用上下文管理器實(shí)現(xiàn)奴拦。

import threading
from contextlib import contextmanager
_local = threading.local
@contextmanager
def acqurie(*locks):
    locks = sorted(locks,key=lambda x:id(x))
    acquried = getattr(_local,'acquried',[])
    if acquried and max(id(lock) for lock in acquried) >= id(locks[0]):
        raise RuntimeError('Lock order Violation')
    acquried.extend(locks)
    _local.acquried = acquried
    try:
        for lock in locks:
            lock.acqurie()
        yield
    finally:
        for lock in reversed(locks):
            lock.release
        del acquried[-len(locks):]

這樣只用按照正常的方式來分配鎖對(duì)象媒鼓,但是當(dāng)想同一個(gè)或多個(gè)鎖打交道時(shí)就用acquire函數(shù),例如:

import threading
x_lock = threading.Lock()
y_lock = threading.Lock()
 
def thread_1():
  while True:
    with acquire(x_lock, y_lock):
      print('Thread-1')
 
def thread_2():
  while True:
    with acquire(y_lock, x_lock):
      print('Thread-2')
 
t1 = threading.Thread(target=thread_1)
t1.daemon = True
t1.start()
 
t2 = threading.Thread(target=thread_2)
t2.daemon = True
t2.start()

多線程和隊(duì)列

Queue是python標(biāo)準(zhǔn)庫中的線程安全的隊(duì)列(FIFO)實(shí)現(xiàn),提供了一個(gè)適用于多線程編程的先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)错妖,即隊(duì)列绿鸣,用來在生產(chǎn)者和消費(fèi)者線程之間的信息傳遞(python3中的隊(duì)列模塊是queue,不是Queue)

import queue

q = queue.Queue()
for i in range(10):
    q.put(i)
while not q.empty():
    print(q.get())

我們看一下結(jié)果:


Queue模塊中的常用方法:
Queue.qsize() 返回隊(duì)列的大小
Queue.empty() 如果隊(duì)列為空暂氯,返回True,反之False
Queue.full() 如果隊(duì)列滿了潮模,返回True,反之False
Queue.full 與 maxsize 大小對(duì)應(yīng)
Queue.get([block[, timeout]])獲取隊(duì)列,timeout等待時(shí)間
Queue.get_nowait() 相當(dāng)Queue.get(False)
Queue.put(item) 寫入隊(duì)列痴施,timeout等待時(shí)間
Queue.put_nowait(item) 相當(dāng)Queue.put(item, False)
Queue.task_done() 在完成一項(xiàng)工作之后擎厢,Queue.task_done()函數(shù)向任務(wù)已經(jīng)完成的隊(duì)列發(fā)送一個(gè)信號(hào)
Queue.join() 實(shí)際上意味著等到隊(duì)列為空,再執(zhí)行別的操作

我們可以看到get()方法從隊(duì)列移除并返回一個(gè)數(shù)據(jù)辣吃,取出操作可以放在不同的線程中,不會(huì)出現(xiàn)同步的問題动遭。

我們經(jīng)常會(huì)遇到這樣的一個(gè)問題,這里有成千上萬條數(shù)據(jù)神得,每次需要取出其中的一條數(shù)據(jù)進(jìn)行處理厘惦,那么引入多線程該怎么進(jìn)行任務(wù)分配?
我們可以將數(shù)據(jù)進(jìn)行分割然后交給多個(gè)線程去跑哩簿,可是這并不是一個(gè)明智的做法宵蕉。在這里我們可以使用隊(duì)列與線程相結(jié)合的方式進(jìn)行任務(wù)分配。
隊(duì)列線程的思想: 首先創(chuàng)建一個(gè)全局共享的隊(duì)列节榜,隊(duì)列中只存在有限個(gè)元素羡玛,并將所有的數(shù)據(jù)逐條加入到隊(duì)列中,并調(diào)用隊(duì)列的join函數(shù)進(jìn)行等待宗苍。之后便可以開啟若干線程缝左,線程的任務(wù)就是不斷的從隊(duì)列中取數(shù)據(jù)進(jìn)行處理就可以了。

線程間通信最安全的做法就是使用queue浓若,首先創(chuàng)建一個(gè)queue實(shí)例渺杉,他會(huì)被所有的線程共享,之后可以使用put()或get()給隊(duì)列添加刪除元素挪钓。queue已經(jīng)擁有了所有所需的鎖是越,所以可以安全的在任意多的線程之間共享。

import time 
import queue
import threading

def printf(q):
    while not q.empty():
        print(threading.current_thread().name)
        print(q.get())
        time.sleep(1)
        q.task_done()
def main():
    q = queue.Queue()
    for i in range(100):
        q.put(i)
    for i in range(10):
        t = threading.Thread(target=printf,args=(q,))
        t.setDaemon(True)
        t.start()
    q.join()
    print('End')

if __name__ == '__main__':
    main()

我們構(gòu)造一個(gè)一百個(gè)數(shù)字的隊(duì)列碌上,看一下都是哪個(gè)線程在完成任務(wù):

漏洞社區(qū)的文章中還設(shè)置了守護(hù)線程(daemon)倚评,首先知道當(dāng)我們創(chuàng)建了一個(gè)線程實(shí)例方法時(shí)浦徊,在調(diào)用它的start()方法之前,線程不會(huì)立刻開始執(zhí)行天梧,線程實(shí)例會(huì)在他們所屬的系統(tǒng)級(jí)線程(POSIX或者Windows)中執(zhí)行盔性,這些線程完全由操作系統(tǒng)來管理,一旦啟動(dòng)后呢岗,線程就開始獨(dú)立運(yùn)行冕香,直到目標(biāo)函數(shù)返回位置,當(dāng)我們請(qǐng)求連接(join)到某個(gè)線程時(shí)后豫,會(huì)等待該線程結(jié)束悉尾,解釋器會(huì)一直保持運(yùn)行,直到所有的線程結(jié)束挫酿,對(duì)于需要長時(shí)間運(yùn)行或者一直不斷運(yùn)行的線程我們應(yīng)該設(shè)置守護(hù)線程构眯,daemon線程無法被連接,但是當(dāng)主線程結(jié)束后他們會(huì)自動(dòng)銷毀早龟。

多進(jìn)程 VS 多線程

多進(jìn)程/多線程:
表示可以同時(shí)執(zhí)行多個(gè)任務(wù)惫霸,進(jìn)程和線程的調(diào)度是由操作系統(tǒng)自動(dòng)完成。
進(jìn)程:每個(gè)進(jìn)程都有自己獨(dú)立的內(nèi)存空間葱弟,不同進(jìn)程之間的內(nèi)存空間不共享它褪。
進(jìn)程之間的通信有操作系統(tǒng)傳遞,導(dǎo)致通訊效率低翘悉,切換開銷大。
線程:一個(gè)進(jìn)程可以有多個(gè)線程居触,所有線程共享進(jìn)程的內(nèi)存空間妖混,通訊效率高,切換開銷小轮洋。
共享意味著競爭制市,導(dǎo)致數(shù)據(jù)不安全,為了保護(hù)內(nèi)存空間的數(shù)據(jù)安全弊予,引入"互斥鎖"祥楣。
一個(gè)線程在訪問內(nèi)存空間的時(shí)候,其他線程不允許訪問汉柒,必須等待之前的線程訪問結(jié)束误褪,才能使用這個(gè)內(nèi)存空間。
互斥鎖:一種安全有序的讓多個(gè)線程訪問內(nèi)存空間的機(jī)制碾褂。
Python的多線程:
GIL 全局解釋器鎖:線程的執(zhí)行權(quán)限兽间,在Python的進(jìn)程里只有一個(gè)GIL。
一個(gè)線程需要執(zhí)行任務(wù)正塌,必須獲取GIL嘀略。
好處:直接杜絕了多個(gè)線程訪問內(nèi)存空間的安全問題恤溶。
壞處:Python的多線程不是真正多線程,不能充分利用多核CPU的資源帜羊。
但是咒程,在I/O阻塞的時(shí)候,解釋器會(huì)釋放GIL讼育。
所以:
多進(jìn)程:密集CPU任務(wù)帐姻,需要充分使用多核CPU資源(服務(wù)器,大量的并行計(jì)算)的時(shí)候窥淆,用多進(jìn)程卖宠。 multiprocessing
缺陷:多個(gè)進(jìn)程之間通信成本高,切換開銷大忧饭。
多線程:密集I/O任務(wù)(網(wǎng)絡(luò)I/O扛伍,磁盤I/O,數(shù)據(jù)庫I/O)使用多線程合適词裤。
threading.Thread刺洒、multiprocessing.dummy
缺陷:同一個(gè)時(shí)間切片只能運(yùn)行一個(gè)線程,不能做到高并行吼砂,但是可以做到高并發(fā)逆航。
協(xié)程:又稱微線程,在單線程上執(zhí)行多個(gè)任務(wù)渔肩,用函數(shù)切換因俐,開銷極小。不通過操作系統(tǒng)調(diào)度周偎,沒有進(jìn)程抹剩、線程的切換開銷。genvent蓉坎,monkey.patchall
多線程請(qǐng)求返回是無序的澳眷,那個(gè)線程有數(shù)據(jù)返回就處理那個(gè)線程,而協(xié)程返回的數(shù)據(jù)是有序的蛉艾。
缺陷:單線程執(zhí)行钳踊,處理密集CPU和本地磁盤IO的時(shí)候,性能較低勿侯。處理網(wǎng)絡(luò)I/O性能還是比較高.

異步IO

我們已經(jīng)知道拓瞪,CPU的速度遠(yuǎn)遠(yuǎn)快于磁盤、網(wǎng)絡(luò)等IO助琐。在一個(gè)線程中吴藻,CPU執(zhí)行代碼的速度極快,然而弓柱,一旦遇到IO操作沟堡,如讀寫文件侧但、發(fā)送網(wǎng)絡(luò)數(shù)據(jù)時(shí),就需要等待IO操作完成航罗,才能繼續(xù)進(jìn)行下一步操作禀横。這種情況稱為同步IO。
在IO操作的過程中粥血,當(dāng)前線程被掛起柏锄,而其他需要CPU執(zhí)行的代碼就無法被當(dāng)前線程執(zhí)行了。
因?yàn)橐粋€(gè)IO操作就阻塞了當(dāng)前線程复亏,導(dǎo)致其他代碼無法執(zhí)行趾娃,所以我們必須使用多線程或者多進(jìn)程來并發(fā)執(zhí)行代碼,為多個(gè)用戶服務(wù)缔御。每個(gè)用戶都會(huì)分配一個(gè)線程抬闷,如果遇到IO導(dǎo)致線程被掛起,其他用戶的線程不受影響耕突。
多線程和多進(jìn)程的模型雖然解決了并發(fā)問題笤成,但是系統(tǒng)不能無上限地增加線程。由于系統(tǒng)切換線程的開銷也很大眷茁,所以炕泳,一旦線程數(shù)量過多,CPU的時(shí)間就花在線程切換上了上祈,真正運(yùn)行代碼的時(shí)間就少了培遵,結(jié)果導(dǎo)致性能嚴(yán)重下降。
由于我們要解決的問題是CPU高速執(zhí)行能力和IO設(shè)備的龜速嚴(yán)重不匹配登刺,多線程和多進(jìn)程只是解決這一問題的一種方法籽腕。
另一種解決IO問題的方法是異步IO。當(dāng)代碼需要執(zhí)行一個(gè)耗時(shí)的IO操作時(shí)塘砸,它只發(fā)出IO指令,并不等待IO結(jié)果晤锥,然后就去執(zhí)行其他代碼了掉蔬。一段時(shí)間后,當(dāng)IO返回結(jié)果時(shí)矾瘾,再通知CPU進(jìn)行處理女轿。

協(xié)程由于具有極高的執(zhí)行效率,因?yàn)樽映绦虻那袚Q不是線程切換壕翩,而是程序自身控制蛉迹,所以沒有線程切換的開銷,所以線程越多協(xié)程性能優(yōu)勢越明顯放妈,而且不需要鎖機(jī)制北救,因?yàn)橹挥幸粋€(gè)線程荐操,也不存在寫變量沖突,為了利用多核cpu珍策,可以采用多進(jìn)程+協(xié)程托启,充分發(fā)揮協(xié)程的高效率,也可以利用多核攘宙,可以獲得極高的性能屯耸。

腳本優(yōu)化

我本身的腳本是通過post對(duì)某網(wǎng)站進(jìn)行用戶名密碼驗(yàn)證,現(xiàn)打算用多進(jìn)程 + 協(xié)程進(jìn)行并發(fā)優(yōu)化蹭劈。
由于requests庫提供的相關(guān)方法不是可等待對(duì)象(awaitable),使得無法放在await后面疗绣,因此無法使用requests庫在協(xié)程程序中實(shí)現(xiàn)請(qǐng)求,在此铺韧,官方專門提供了一個(gè)aiohttp庫多矮,用來實(shí)現(xiàn)異步網(wǎng)頁請(qǐng)求等功能,詳情請(qǐng)參閱官方文檔祟蚀。


我又被客戶爸爸ban了工窍,等我從小黑屋里放出來再更新吧。

參考鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末前酿,一起剝皮案震驚了整個(gè)濱河市患雏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌罢维,老刑警劉巖淹仑,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異肺孵,居然都是意外死亡匀借,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門平窘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吓肋,“玉大人,你說我怎么就攤上這事瑰艘∈枪恚” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵紫新,是天一觀的道長均蜜。 經(jīng)常有香客問我,道長芒率,這世上最難降的妖魔是什么囤耳? 我笑而不...
    開封第一講書人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上充择,老公的妹妹穿的比我還像新娘德玫。我一直安慰自己,他們只是感情好聪铺,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開白布化焕。 她就那樣靜靜地躺著,像睡著了一般铃剔。 火紅的嫁衣襯著肌膚如雪撒桨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評(píng)論 1 290
  • 那天键兜,我揣著相機(jī)與錄音凤类,去河邊找鬼。 笑死普气,一個(gè)胖子當(dāng)著我的面吹牛谜疤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播现诀,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼夷磕,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了仔沿?” 一聲冷哼從身側(cè)響起坐桩,我...
    開封第一講書人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎封锉,沒想到半個(gè)月后绵跷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡成福,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年碾局,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奴艾。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡净当,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蕴潦,到底是詐尸還是另有隱情像啼,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布品擎,位于F島的核電站埋合,受9級(jí)特大地震影響备徐,放射性物質(zhì)發(fā)生泄漏萄传。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望秀菱。 院中可真熱鬧振诬,春花似錦、人聲如沸衍菱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽脊串。三九已至辫呻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間琼锋,已是汗流浹背放闺。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缕坎,地道東北人怖侦。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像谜叹,于是被迫代替她去往敵國和親匾寝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348