通过信号量执行线程同步后,无法同时运行三个线程

2024-10-01 04:58:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我能够使用信号量值设置为1的信号量获得以下多线程代码的顺序输出。但是,现在不是3个进程同时运行,而是一次只运行一个线程。有没有一种方法可以让我同时运行三个线程,同时也可以获得顺序输出

from datetime import datetime
import getpass
import os
import sys
import time
import re
import json
from random import random
import threading
from io import StringIO
from time import gmtime, strftime
from pprint import pprint
from threading import *
screen_lock = Semaphore(value=1)

#------------------------------------------------------------------------------
def config_worker(port):
    if port == 'a':
       screen_lock.acquire()
       print('PASS : Tunnel1 is UP from  router 1')
       print('PASS : Tunnel2 is UP from  router 1')
       print('PASS : Tunnel3 is UP from  router 1')
       screen_lock.release()
       
    if port == 'b':
       screen_lock.acquire()
       print('PASS : Tunnel1 is UP from  router 2')
       print('PASS : Tunnel2 is UP from  router 2')
       print('PASS : Tunnel3 is UP from  router 2')
       screen_lock.release()
       
    if port == 'c':
       screen_lock.acquire()
       print('PASS : Tunnel1 is UP from  router 3')
       print('PASS : Tunnel2 is UP from  router 3')
       print('PASS : Tunnel3 is UP from  router 3')
       screen_lock.release()
    return

def connect():

    config_threads_list = []
    devices = ['a','b','c']
    for ports in devices:
        port = ports
        print ('Creating thread for: ', ports)
        config_threads_list.append(threading.Thread(target=config_worker, args=(port)))

    print ('\n---- Begin get config threading ----\n')
    for config_thread in config_threads_list:
        config_thread.start()

    for config_thread in config_threads_list:
        config_thread.join()



connect()
 

带信号量的输出。输出是正确的,但一次只运行一个线程。如何运行所有线程并打印顺序输出

---- Begin get config threading ----

PASS : Tunnel1 is UP from  router 1
PASS : Tunnel2 is UP from  router 1
PASS : Tunnel3 is UP from  router 1
PASS : Tunnel1 is UP from  router 2
PASS : Tunnel2 is UP from  router 2
PASS : Tunnel3 is UP from  router 2
PASS : Tunnel1 is UP from  router 3
PASS : Tunnel2 is UP from  router 3
PASS : Tunnel3 is UP from  router 3

Tags: fromimportconfiglockisportpassscreen
2条回答

最可能的问题是GIL锁。试试multiprocessing.pool

from multiprocessing import Pool

def connect():
    po = Pool(3)
    res = po.map(config_worker, devices)

正在运行所有线程-您可以看出这一点,因为所有输出都已生成

由于信号量的原因,语句总是以三个块的形式出现

如果您想要更随机的序列,请尝试添加睡眠(我还添加了一个打印以显示哪个端口线程正在启动):

from datetime import datetime
import getpass
import os
import sys
import time
import re
import json
from random import random
import threading
from io import StringIO
from time import gmtime, strftime
from pprint import pprint
from threading import *
screen_lock = Semaphore(value=1)

#                                       
def config_worker(port):
    print( f"Starting thread {port}" )   # ADDED
    time.sleep(0.0001)                   # ADDED
    if port == 'a':
       screen_lock.acquire()
       print('PASS : Tunnel1 is UP from  router 1')
       print('PASS : Tunnel2 is UP from  router 1')
       print('PASS : Tunnel3 is UP from  router 1')
       screen_lock.release()
       
    if port == 'b':
       screen_lock.acquire()
       print('PASS : Tunnel1 is UP from  router 2')
       print('PASS : Tunnel2 is UP from  router 2')
       print('PASS : Tunnel3 is UP from  router 2')
       screen_lock.release()
       
    if port == 'c':
       screen_lock.acquire()
       print('PASS : Tunnel1 is UP from  router 3')
       print('PASS : Tunnel2 is UP from  router 3')
       print('PASS : Tunnel3 is UP from  router 3')
       screen_lock.release()
    return

def connect():

    config_threads_list = []
    devices = ['a','b','c']
    for ports in devices:
        port = ports
        print ('Creating thread for: ', ports)
        config_threads_list.append(threading.Thread(target=config_worker, args=(port)))

    print ('\n   Begin get config threading   \n')
    for config_thread in config_threads_list:
        config_thread.start()

    for config_thread in config_threads_list:
        config_thread.join()



connect()

现在,当您运行此代码时,可以获得不同的序列,请尝试几次:

首次运行:

Creating thread for:  a
Creating thread for:  b
Creating thread for:  c

   Begin get config threading   

Starting thread a
Starting thread b
Starting thread c
PASS : Tunnel1 is UP from  router 3
PASS : Tunnel2 is UP from  router 3
PASS : Tunnel3 is UP from  router 3
PASS : Tunnel1 is UP from  router 1
PASS : Tunnel2 is UP from  router 1
PASS : Tunnel3 is UP from  router 1
PASS : Tunnel1 is UP from  router 2
PASS : Tunnel2 is UP from  router 2
PASS : Tunnel3 is UP from  router 2

第二轮:

Creating thread for:  a
Creating thread for:  b
Creating thread for:  c

   Begin get config threading   

Starting thread a
Starting thread b
Starting thread c
PASS : Tunnel1 is UP from  router 2
PASS : Tunnel2 is UP from  router 2
PASS : Tunnel3 is UP from  router 2
PASS : Tunnel1 is UP from  router 1
PASS : Tunnel2 is UP from  router 1
PASS : Tunnel3 is UP from  router 1
PASS : Tunnel1 is UP from  router 3
PASS : Tunnel2 is UP from  router 3
PASS : Tunnel3 is UP from  router 3

或者,如果注释掉screen_lock.acquire()/screen_lock.release()行,则会得到一个更混乱的序列(在本例中,我保留了睡眠(0.0001),但没有睡眠,序列也会发生变化,可能是因为线程打开了打印的I/O):

Creating thread for:  a
Creating thread for:  b
Creating thread for:  c

   Begin get config threading   

Starting thread a
Starting thread b
Starting thread c
PASS : Tunnel1 is UP from  router 3
PASS : Tunnel1 is UP from  router 1
PASS : Tunnel2 is UP from  router 3
PASS : Tunnel2 is UP from  router 1
PASS : Tunnel3 is UP from  router 3
PASS : Tunnel3 is UP from  router 1
PASS : Tunnel1 is UP from  router 2
PASS : Tunnel2 is UP from  router 2
PASS : Tunnel3 is UP from  router 2

相关问题 更多 >