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
htop
Eine detaillierte Prozessliste kann über den Befehl angezeigt werden.
Hinweis: kill -9 pid
Nach 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()