日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

并发服务器的信号传递,使服务器支持并发、GIL全局解释器锁、死锁和Rlock、信号量、event事件、...

發布時間:2023/12/19 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 并发服务器的信号传递,使服务器支持并发、GIL全局解释器锁、死锁和Rlock、信号量、event事件、... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

服務器的并發實現:

服務端:

importsocketfrom threading importThread"""服務端

1.要有固定的IP和PORT

2.24小時不間斷提供服務

3.能夠支持并發"""server=socket.socket()

server.bind((‘127.0.0.1‘,8080))

server.listen(5)deftalk(conn):whileTrue:try:

data= conn.recv(1024)if len(data) == 0:break

print(data.decode(‘utf-8‘))

conn.send(data.upper())exceptConnectionResetError as e:print(e)breakconn.close()"""當有客戶端過來連接的時候,先執行while循環中的代碼,

開啟一個線程去服務這個客戶端,當有客戶端再過來連的時候,

可以再開啟一個線程去服務一個客戶端"""

whileTrue:

conn, addr= server.accept() #監聽 等待客戶端的連接 阻塞態

print(addr)

t= Thread(target=talk, args=(conn,))

t.start()

View Code

客戶端:

importsocket

client=socket.socket()

client.connect((‘127.0.0.1‘,8080))whileTrue:

client.send(b‘hello‘)

data= client.recv(1024)print(data.decode(‘utf-8‘))

View Code

GIL全局解釋器鎖:

Python代碼的執行由Python虛擬機(也叫解釋器主循環)來控制。Python在設計之初就考慮到要在主循環中,同時只有一個線程在執行。

雖然 Python 解釋器中可以“運行”多個線程,但在任意時刻只有一個線程在解釋器中運行。

對Python虛擬機的訪問由全局解釋器鎖(GIL)來控制,正是這個鎖能保證同一時刻只有一個線程在運行。

GIL本質也是一把互斥鎖:將并發變成串行犧牲效率保證數據的安全

用來阻止同一個進程下的多個線程的同時執行(同一個進程內多個線程無法實現并行但是可以實現并發)

GIL的存在是因為CPython解釋器的內存管理不是線程安全的

如果同時運行,那么線程中的值可能還沒有被使用就被垃圾回收機制進行回收了,所以CPython解釋器的內存管理不是線程安全的,要有GIL。

垃圾回收機制

1.引用計數

2.標記清除

3.分代回收

研究python的多線程是否有用需要分情況討論:

四個任務 計算密集型的

單核情況下

開線程更省資源

多核情況下

開進程

開線程

四個任務IO密集型的

單核情況下

開線程更節省資源

多核情況下

開線程更節省資源

代碼驗證:

計算密集型:

計算密集型from multiprocessing importProcessfrom threading importThreadimportos,timedefwork():

res=0for i in range(100000000):

res*=iif __name__ == ‘__main__‘:

l=[]print(os.cpu_count()) #本機為6核

start=time.time()for i in range(6):#p=Process(target=work) #耗時 4.732933044433594

p=Thread(target=work) #耗時 22.83087730407715

l.append(p)

p.start()for p inl:

p.join()

stop=time.time()print(‘run time is %s‘ %(stop-start))

View Code

IO密集型:

from multiprocessing importProcessfrom threading importThreadimportthreadingimportos,timedefwork():

time.sleep(2)if __name__ == ‘__main__‘:

l=[]print(os.cpu_count()) #本機為6核

start=time.time()for i in range(40):#p=Process(target=work) #耗時9.001083612442017s多,大部分時間耗費在創建進程上

p=Thread(target=work) #耗時2.051966667175293s多

l.append(p)

p.start()for p inl:

p.join()

stop=time.time()print(‘run time is %s‘ %(stop-start))

View Code

死鎖和Rlock:

死鎖狀態:也就是不同線程都去等待對方去釋放鎖的情況(互相僵持)

建議:輕易不要去嘗試處理鎖的問題。

from threading importThread,Lock,current_thread,RLockimporttime"""Rlock可以被第一個搶到鎖的人連續的acquire和release

每acquire一次鎖身上的計數加1

每release一次鎖身上的計數減1

只要鎖的計數不為0 其他人都不能搶"""

#mutexA = Lock()#mutexB = Lock()

mutexA = mutexB = RLock() #A B現在是同一把鎖

classMyThread(Thread):def run(self): #創建線程自動觸發run方法 run方法內調用func1 func2相當于也是自動觸發

self.func1()

self.func2()deffunc1(self):

mutexA.acquire()print(‘%s搶到了A鎖‘%self.name) #self.name等價于current_thread().name

mutexB.acquire()print(‘%s搶到了B鎖‘%self.name)

mutexB.release()print(‘%s釋放了B鎖‘%self.name)

mutexA.release()print(‘%s釋放了A鎖‘%self.name)deffunc2(self):

mutexB.acquire()print(‘%s搶到了B鎖‘%self.name)

time.sleep(1)

mutexA.acquire()print(‘%s搶到了A鎖‘ %self.name)

mutexA.release()print(‘%s釋放了A鎖‘ %self.name)

mutexB.release()print(‘%s釋放了B鎖‘ %self.name)for i in range(10):

t=MyThread()

t.start()

View Code

信號量:

過程:

先有五個線程同時獲得鎖,然后運行完因為不同線程睡眠時間不同所以釋放時間也會不同,

之后先釋放出來的鎖便可以讓其他線程再去搶奪。

#信號量可能在不同的領域中 對應不同的知識點

"""互斥鎖:一個廁所(一個坑位)

信號量:公共廁所(多個坑位)"""

from threading importSemaphore,Threadimporttimeimportrandom

sm= Semaphore(5) #造了一個含有五個的坑位的公共廁所

deftask(name):

sm.acquire()print(‘%s占了一個坑位‘%name)

time.sleep(random.randint(1,3))

sm.release()for i in range(40):

t= Thread(target=task,args=(i,))

t.start()

View Code

envent事件:

from threading importEvent, Threadimporttime#先生成一個event對象

e =Event()deflight():print(‘紅燈正亮著‘)

time.sleep(3)

e.set()#發信號

print(‘綠燈亮了‘)defcar(name):print(‘%s正在等紅燈‘%name)

e.wait()#等待信號

print(‘%s加油門飆車了‘%name)

t= Thread(target=light)

t.start()for i in range(10):

t= Thread(target=car,args=(‘傘兵%s‘%i,))

t.start()"""先啟一個線程,打印路燈亮了,進入睡眠的同時,起了十個線程,之后打印正在等綠燈,

之后等待e.wait()收到信號,當運行e.set()發信號時,便可以繼續運行了。"""

View Code

線程queue:

importqueue"""同一個進程下的多個線程本來就是數據共享 為什么還要用隊列

因為隊列是管道+鎖 使用隊列你就不需要自己手動操作鎖的問題

因為鎖操作的不好極容易產生死鎖現象"""

#q = queue.Queue()#q.put(‘hahha‘)#print(q.get())

#q = queue.LifoQueue()#后進先出#q.put(1)#q.put(2)#q.put(3)#print(q.get())

#q = queue.PriorityQueue()## 數字越小 優先級越高#q.put((10,‘haha‘))#q.put((100,‘hehehe‘))#q.put((0,‘xxxx‘))#q.put((-10,‘yyyy‘))#print(q.get())

View Code

原文:https://www.cnblogs.com/yangjiaoshou/p/11353187.html

總結

以上是生活随笔為你收集整理的并发服务器的信号传递,使服务器支持并发、GIL全局解释器锁、死锁和Rlock、信号量、event事件、...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。