従来のプログラミングの欠点
従来のプログラミングの欠点:
# 必须按照顺序执行,多个任务无法同时在还行
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()
2 つのタスクに費やす時間は 10 秒です。実際に、踊りと歌を同時にやりたい場合は、最も長いタスクが完了した時点で 2 つのタスクを完了することができます。
マルチプロセス、マルチスレッド、コルーチンなど、マルチタスク プログラミングを実装するにはさまざまな方法があります。
2. マルチプロセス方式でマルチタスクを実現
# 必须按照顺序执行,多个任务无法同时在还行
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()
3つのプロセスの一部の操作
詳細なプロセスのリストは、コマンドを通じてhtop
表示できます。
注:kill -9 pid
メイン プロセスを強制終了した後、子プロセスは強制終了されません。この時点では、このコマンドのシグナルがメイン プロセスに送信されて強制終了タスクを実行するため、コマンド ラインは正常に終了できません。プロセスには親プロセスがありません。 は孤立プロセスとなり、後に init プロセスに採用されました。つまり、メインプロセスを強制終了した後、子プロセスの親プロセスは init プロセスと呼ばれます。
を通じて、os.getpid()
現在のプロセスの pid とos.getppid()
親プロセスの id を取得できます。
4つのプロセス間通信
プロセスは独立したアプリケーションであるため、プロセス同士は直接通信できません。
プロセス間の通信を実現するための一般的なメソッドには、ソケットなどがあります。Python では、キュー メソッドを使用して以下を実現できます。
queue = multiprocessing.Queue(3)
queue.put("111")
queue.put(222)
# 取数据
res = queue.get()
print(res)
# 判断: q.full() q.empty()
5 つのプロセス プール
p = multiprocessing.Pool(3)
マルチタスクを実現する6つのマルチスレッド方式
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()
7つのスレッド関連API
threading.Thread()
スレッドを作成し、threading.enumerate()
現在のすべてのスレッドを表示できます。
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. 同期とデッドロック
スレッドはグローバル変数を共有するため、データの混乱が生じます。
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()
ミューテックス ロックを使用して同期を実現する解決策:
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()