Python-Prozesse, Multiprozesse, Threads sowie Synchronisierung und Deadlocks

Ein Manko der traditionellen Programmierung

Nachteile der traditionellen Programmierung:

# 必须按照顺序执行,多个任务无法同时在还行
import time


def sing():
    for i in range(5):
        print("sing: hero")
        time.sleep(1)       # 每唱一次,等1秒再唱


def dance():
    for i in range(5):
        print("dance: swan")
        time.sleep(1)       # 每唱一次,等1秒再跳


def main():
    sing()
    dance()


if __name__ == "__main__":
    main()

Der Zeitaufwand für die beiden Aufgaben beträgt 10 Sekunden. Wenn Sie gleichzeitig tanzen und singen möchten, können die beiden Aufgaben tatsächlich erledigt werden, wenn die längste Aufgabe erledigt ist.

Es gibt viele Möglichkeiten, Multitasking-Programmierung zu implementieren, z. B. Multiprozess, Multithread, Coroutine usw.

2. Verwenden Sie die Multiprozessmethode, um Multitasking zu erreichen

# 必须按照顺序执行,多个任务无法同时在还行
import time
import multiprocessing


def sing():
    for i in range(5):
        print("sing: hero")
        time.sleep(1)       # 每唱一次,等1秒再唱


def dance():
    for i in range(5):
        print("dance: swan")
        time.sleep(1)       # 每唱一次,等1秒再跳


def main():
    p1 = multiprocessing.Process(target=sing)
    p2 = multiprocessing.Process(target=dance)
    p1.start()
    p2.start()


if __name__ == "__main__":
    main()

Einige Operationen der drei Prozesse

htopEine detaillierte Prozessliste kann über den Befehl angezeigt werden.

Hinweis: kill -9 pidNach dem Beenden des Hauptprozesses wird der untergeordnete Prozess nicht beendet. Zu diesem Zeitpunkt kann die Befehlszeile nicht normal beendet werden, da das Signal dieses Befehls an den Hauptprozess gesendet wird, um die Tötungsaufgabe auszuführen. Das Kind Der Prozess hat keinen übergeordneten Prozess. Er wurde zu einem verwaisten Prozess und wurde später vom Init-Prozess übernommen. Das heißt, nach dem Beenden des Hauptprozesses wird der übergeordnete Prozess des untergeordneten Prozesses als Init-Prozess bezeichnet.

Über os.getpid()können Sie die PID des aktuellen Prozesses und os.getppid()die ID des übergeordneten Prozesses abrufen.

Vier prozessübergreifende Kommunikation

Prozesse können nicht direkt miteinander kommunizieren, da es sich um unabhängige Anwendungen handelt.

Um die Kommunikation zwischen Prozessen zu erreichen, gehören zu den gängigen Methoden: Socket usw. In Python können Sie die Warteschlangenmethode verwenden, um Folgendes zu erreichen:

queue = multiprocessing.Queue(3)
queue.put("111")
queue.put(222)

# 取数据
res = queue.get()
print(res)
# 判断: q.full()  q.empty()

Fünf Prozesspool

p = multiprocessing.Pool(3)

Sechs Multithreading-Methoden zur Erzielung von Multitasking

import time
import threading


def sing():
    for i in range(5):
        print("sing: hero")
        time.sleep(1)       # 每唱一次,等1秒再唱


def dance():
    for i in range(5):
        print("dance: swan")
        time.sleep(1)       # 每唱一次,等1秒再跳


def main():
    t1 = threading.Thread(target=sing)      # 创建一个线程对象
    t2 = threading.Thread(target=dance)     # 创建一个线程对象
    t1.start()                              # 开启线程
    t2.start()                              # 开启线程


if __name__ == "__main__":
    main()

Sieben Thread-bezogene API

threading.Thread() Es können Threads erstellt und threading.enumerate()alle aktuellen Threads angezeigt werden:

import time
import threading


def sing():
    for i in range(5):
        print("sing: hero")
        time.sleep(1)       # 每唱一次,等1秒再唱


def dance():
    for i in range(5):
        print("dance: swan")
        time.sleep(1)       # 每唱一次,等1秒再跳


def main():

    t1 = threading.Thread(target=sing)
    t2 = threading.Thread(target=dance)

    t1.start()
    t2.start()

    while True:
        length = len(threading.enumerate())
        print("当前线程数为:%d" % length)
        if length <= 1:
            break
        time.sleep(0.5)


if __name__ == "__main__":
    main()

8. Synchronisation und Deadlock

Threads teilen globale Variablen, was zu Datenverwirrung führt:

import time
import threading

# 定义共享的全局变量
num = 0


def add100():
    global num
    for i in range(100000):
        num = num + 0.00001


def add1000():
    global num
    for i in range(100000):
        num = num + 1000


def main():

    t1 = threading.Thread(target=add100)
    t2 = threading.Thread(target=add1000)

    t1.start()
    t2.start()

    time.sleep(5)
    print(num)              # 每次输出的结果是不相同的


if __name__ == "__main__":
    main()

Lösung zur Verwendung von Mutex-Sperren zur Erzielung einer Synchronisierung:

import time
import threading

# 定义共享的全局变量
num = 0


def add100():
    global num
    mutex.acquire()     # 加锁:若已经加锁,则会直到锁被揭开
    for i in range(100000):
        num = num + 0.00001
    mutex.release()     # 解锁


def add1000():
    global num
    mutex.acquire()     # 加锁:若已经加锁,则会直到锁被揭开
    for i in range(100000):
        num = num + 1000
    mutex.release()     # 解锁


# 创建互斥锁,默认不会上锁
mutex = threading.Lock()


def main():

    t1 = threading.Thread(target=add100)
    t2 = threading.Thread(target=add1000)

    t1.start()
    t2.start()

    time.sleep(5)
    print(num)          # 100000001.0 永远不会变


if __name__ == "__main__":
    main()

Ich denke du magst

Origin blog.csdn.net/weixin_51390582/article/details/135549585
Empfohlen
Rangfolge