Uma deficiência da programação tradicional
Desvantagens da programação tradicional:
# 必须按照顺序执行,多个任务无法同时在还行
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()
O tempo gasto nas duas tarefas é de 10 segundos. Se você quiser dançar e cantar ao mesmo tempo, na verdade, as duas tarefas podem ser concluídas quando a tarefa mais longa for concluída.
Existem muitas maneiras de implementar programação multitarefa, como: multiprocesso, multithread, corrotina, etc.
2. Use o método multiprocesso para realizar multitarefa
# 必须按照顺序执行,多个任务无法同时在还行
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()
Algumas operações dos três processos
htop
Uma lista detalhada de processos pode ser visualizada através do comando.
Nota: kill -9 pid
Após encerrar o processo principal, o processo filho não será eliminado. Neste momento, a linha de comando não poderá sair normalmente porque o sinal deste comando é enviado ao processo principal para executar a tarefa de eliminação. O filho process não possui um processo pai. , tornou-se um processo órfão e posteriormente foi adotado pelo processo init. Ou seja, depois de eliminar o processo principal, o processo pai do processo filho é chamado de processo init.
Através de , os.getpid()
você pode obter o pid do processo atual e os.getppid()
o id do processo pai.
Quatro comunicação entre processos
Os processos não podem se comunicar diretamente entre si porque são aplicativos independentes.
Para conseguir a comunicação entre processos, os métodos comuns incluem: soquete, etc. Em Python, você pode usar o método queue para conseguir:
queue = multiprocessing.Queue(3)
queue.put("111")
queue.put(222)
# 取数据
res = queue.get()
print(res)
# 判断: q.full() q.empty()
Conjunto de cinco processos
p = multiprocessing.Pool(3)
Seis métodos multithreading para realizar multitarefa
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()
API relacionada a sete threads
threading.Thread()
Threads podem ser criados e threading.enumerate()
todos os threads atuais podem ser visualizados:
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. Sincronização e impasse
Threads compartilham variáveis globais, o que causará confusão nos dados:
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()
Solução para usar bloqueios mutex para obter sincronização:
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()