再帰的ロック、セマフォ、GILロック、ソケットベースの通信とプロセスマルチスレッドのスレッドプールのプール

再帰的ロック、セマフォ、GILロック、ソケットベースの通信とプロセスマルチスレッドのスレッドプールのプール

再帰的ロック

デッドロック:これは、2つの以上のプロセスと相互待機起因するコンピュータのリソースを奪うによるスレッドの現象を指し

from threading import Thread
from threading import Lock
import time
lock_A = Lock()
lock_B = Lock()
class MyThread(Thread):
    def run(self):
        self.f1()
        self.f2()
    def f1(self):
        lock_A.acquire()
        print(f"{self.name}拿到了A锁")
        lock_B.acquire()
        print(f"{self.name}拿到了B锁")
        lock_B.release()
        lock_A.release()
    def f2(self):
        lock_B.acquire()
        print(f"{self.name}拿到了B锁")
        time.sleep(0.1)
        lock_A.acquire()
        print(f"{self.name}拿到了A锁")
        lock_A.release()
        lock_B.release()
if __name__ == '__main__':
    for i in range(3):
        t = MyThread()
        t.start()
# 结果:
Thread-1拿到了A锁
Thread-1拿到了B锁
Thread-1拿到了B锁
Thread-2拿到了A锁

再帰的ロック:

再帰的ロックが、元の数が0である、ロック時間、1 +カウントカウントする機能を有し、ロックが-1カウント、一度解除され、

限り上記再帰デジタルロックがゼロでないように、他のスレッドがロックを取得することができません。

from threading import Thread
from threading import RLock
import time
lock_A = lock_B = RLock()
class MyThread(Thread):
    def run(self):
        self.f1()
        self.f2()
    def f1(self):
        lock_A.acquire()
        print(f"{self.name}拿到了A锁")
        lock_B.acquire()
        print(f"{self.name}拿到了B锁")
        lock_B.release()
        lock_A.release()
    def f2(self):
        lock_B.acquire()
        print(f"{self.name}拿到了B锁")
        time.sleep(0.1)
        lock_A.acquire()
        print(f"{self.name}拿到了A锁")
        lock_A.release()
        lock_B.release()
if __name__ == '__main__':
    for i in range(3):
        t = MyThread()
        t.start()

セマフォ

また、ロックされ、同時の数を制御

from threading import Thread,Semaphore,current_thread
import time
import random
sem = Semaphore(5)
def task():
    sem.acquire()
    print(f"{current_thread().name}厕所ing")
    time.sleep(random.randint(1,3))
    print(f"{current_thread().name}厕所ed")
    sem.release()
if __name__ == '__main__':
    for i in range(20):
        t = Thread(target=task,)
        t.start()

GILロック

GILロックの定義:

グローバルインタプリタロックがミューテックスあり、それはデータセキュリティ通訳を確保、効率性を犠牲にする、インタプリタのリソースを使用して一度に同時シリアル、一つのスレッドだけになります。

メモリ内のPYファイルの実行処理:

  • Pyのファイルを実行するとき、それはメモリ内のプロセスを開きます。
  • プロセスだけでなく、文書だけでなく、PythonインタプリタのPYを含み、コードのスレッドでPYファイルがインタプリタに引き渡されます、
  • インタプリタC言語コード・バイトにPythonコードを識別することができ、その後、バイナリコードに仮想マシンインタプリタバイトコードのCPUには、最終的に行います

実行スレッド1人の出会い閉塞やCPUが実行時間の期間は、スレッド1が中断されるときGILロックが、この時点でリリースされる一方、最初のスレッドは、1 2 3スレッドだけ待つことができるGILロック糸を、取得するとき一定期間後に閉塞または実行に直面したときGILロックは最後のスレッドがインタプリタを入力します。この時点でリリースされる一方で、スレッド2または3のスレッドがインタプリタにロックされます、あまりにも、CPUは、一時停止を実行します。

上記から分かるように伴うロックGILの存在のために、複数のスレッドを含む単一のプロセスに直面したとき、CPythonのは、マルチコア並列処理を使用するが、単一のコア上で同時に実施することができるではありません。

しかし、複数のコアを活用することができ、異なるプロセス間でマルチスレッド。

GILは二つの効果をロック:

図1は、インタプリタ内のデータの安全性を確保します。

2は、開発負荷の低減、ロックを強制しました

質問:マルチスレッドの単一プロセスは、マルチコアの利点を取ることができません

どのような状況マルチスレッドを使用すると、マルチプロセスの同時実行を確認する方法

計算では、CPUより良い、しかし、I / O、それはより多くの無用のCPUであるため

  もちろん、プログラムを実行し、効率性の向上と、CPUは確かに(、そこには常に改善されますどのくらいの増加の大きさに関係なく)を向上させるプログラムは、実質的に純粋なまたは純粋なコンピューティングではないので、それはI / Oであります次のように、集中又はI / O集中反対側の端に番組を見るように計算されるべきです。

#分析:
我们有四个任务需要处理,处理方式肯定是要达到并发的效果,解决方案可以是:
方案一:开启四个进程
方案二:一个进程下,开启四个线程

#单核情况下,分析结果: 
  如果四个任务是计算密集型,没有多核来并行计算,方案一徒增了创建进程的开销,方案二胜
  如果四个任务是I/O密集型,方案一创建进程的开销大,且进程的切换速度远不如线程,方案二胜

#多核情况下,分析结果:
  如果四个任务是计算密集型,多核意味着并行计算,在python中一个进程中同一时刻只有一个线程执行,可以利用多核,方案一胜
  如果四个任务是I/O密集型,再多的核也解决不了I/O问题,方案二胜


#结论:现在的计算机基本上都是多核,python对于计算密集型的任务开多线程的效率并不能带来多大性能上的提升,甚至不如串行(没有大量切换),但是,对于IO密集型的任务效率还是有显著提升的。

概要:マルチコアの前提の下で、IO集約型のタスク、マルチスレッドを使用する場合、タスクは、より複雑なプロセスを使用して、計算集約的である場合。

同時効率はCPythonの検証

  • 計算集約型:複数のプロセスの単一工程マルチスレッドの同時実行を並列に対
from threading import Thread
from multiprocessing import Process
import time
import random

if __name__ == '__main__':

# 多进程的并发,并行
    start_time = time.time()
    l1 = []
    for i in range(4):
        p = Process(target=task,)
        l1.append(p)
        p.start()

    for p in l1:
        p.join()

    print(f'执行效率:{time.time()- start_time}')  # 2.5342209339141846
from threading import Thread
from multiprocessing import Process
import time
import random

if __name__ == '__main__':
# 多线程的并发
    start_time = time.time()
    l1 = []
    for i in range(4):
        p = Thread(target=task,)
        l1.append(p)
        p.start()

    for p in l1:
        p.join()

    print(f'执行效率:{time.time()- start_time}')  # 5.262923240661621

要約:計算集約型:高効率のマルチ同時並列処理。

  • IO集中型:同時マルチスレッド・シングルプロセス対に並列に複数のプロセスを
from threading import Thread
from multiprocessing import Process
import time
import random

def task():
    count = 0
    time.sleep(random.randint(1,3))
    count += 1

if __name__ == '__main__':

# 多进程的并发,并行
    start_time = time.time()
    l1 = []
    for i in range(50):
        p = Process(target=task,)
        l1.append(p)
        p.start()

    for p in l1:
        p.join()

    print(f'执行效率:{time.time()- start_time}')  #  7.145753383636475
from threading import Thread
from multiprocessing import Process
import time
import random

def task():
    count = 0
    time.sleep(random.randint(1,3))
    count += 1

if __name__ == '__main__':
    start_time = time.time()
    l1 = []
    for i in range(50):
        p = Thread(target=task,)
        l1.append(p)
        p.start()

    for p in l1:
        p.join()

    print(f'执行效率:{time.time()- start_time}')  # 3.0278055667877197

要約:単一プロセスの高効率マルチスレッドの並行性:IO集中について。

マルチスレッドソケット通信に基づきます

クライアント:

import socket

client = socket.socket()

client.connect(('127.0.0.1',8848))

while 1:
    try:
        to_server_data = input('>>>').strip()
        client.send(to_server_data.encode('utf-8'))

        from_server_data = client.recv(1024)
        print(f'来自服务端的消息: {from_server_data.decode("utf-8")}')

    except Exception:
        break
client.close()

サーバー:

import socket
from threading import Thread

def communicate(conn,addr):
    while 1:
        try:
            from_client_data = conn.recv(1024)
            print(f'来自客户端{addr[1]}的消息: {from_client_data.decode("utf-8")}')
            to_client_data = input('>>>').strip()
            conn.send(to_client_data.encode('utf-8'))
        except Exception:
            break
    conn.close()



def _accept():
    server = socket.socket()

    server.bind(('127.0.0.1', 8848))

    server.listen(5)

    while 1:
        conn, addr = server.accept()
        t = Thread(target=communicate,args=(conn,addr))
        t.start()

if __name__ == '__main__':
    _accept()

プロセスプールのスレッドプール

スレッドプール:コンテナはあなたが初めて4つの同時タスクを処理する4などのスレッドの数だけのことを確認することができターンロックされたコンテナは、限り、タスクが完了すると、スレッドはすぐにタスクを引き継ぎます。

from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
import os
import time
import random

# print(os.cpu_count()) 获取cpu数量
def task(n):
    print(f'{os.getpid()} 接客')
    time.sleep(random.randint(1,3))
    
# 开启进程池  (并行(并行+并发))   
if __name__ == '__main__':
    p = ProcessPoolExecutor()  # 进程池,默认不写,开启数量为cpu数量
    for i in range(20):
        p.submit(task,i)
        
    # 开启线程池  (并发)
    t = ThreadPoolExecutor()  # 默认不写, cpu个数*5 线程数
    # t = ThreadPoolExecutor(100)  # 100个线程

    for i in range(20):
        t.submit(task,i)

おすすめ

転載: www.cnblogs.com/lifangzheng/p/11415009.html