2015-05-03 168 views
2

我想了解線程如何在python中工作,並且我對一些事情有些困惑。蟒蛇線程 - 請解釋

我的印象是,你可以在使用線程的同時並行運行不同的任務?

下面的代碼將演示我遇到的一些線程問題。 (我知道寫端口掃描器有更好的方法,但是這會明確我遇到的問題)

============啓動例子========= ===

import socket 
    import threading 

    def test2(start,end): 

     for i in range(int(start),int(end)): 
      server = 'localhost' 
      s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 
      try: 
       s.connect((server,i)) 
       print("port", i , "is open", threading.current_thread().name) 
       s.close() 
      except socket.error as e: 
       s.close() 
    def threader(): 
     print(threading.current_thread().name) 

     if threading.current_thread().name == "Thread-0": 
       test2(1,1000) 

     elif threading.current_thread().name == "Thread-1": 
      test2(1000,2000) 

     elif threading.current_thread().name == "Thread-2": 
      test2(2000,3000) 

     elif threading.current_thread().name == "Thread-3": 
      test2(3000,4000) 

    for i in range(4): 
     t = threading.Thread(target=threader, name= "Thread-"+str(i)) 
     t.start() 

============結束實施例============

如果我將掃描1000個端口,1個螺紋它通常需要7-8秒左右。

上面的代碼的問題是,這需要大約30秒才能執行。

如果所有線程並行運行且正在掃描相同數量的端口,是否需要大約7-8秒才能執行?

我真的很感激,如果有人能解釋我在這裏做錯了什麼。

TIA!

+1

併發性和並行性之間存在差異http://stackoverflow.com/questions/1050222/concurrency-vs-parallelism-what-is-the-difference使用CPython和多線程,只能保證前者,而不是後者,其他的Python實現可能會給你更多的自由度,或者你可以使用多處理。 – Shashank

+0

我無法重現你看到的性能差異。線程代碼對我來說實際上更快,這是有道理的,因爲你在每個線程中執行I/O,這意味着GIL被釋放。對於線程和非線程代碼來說,運行所需的時間也要少於1秒。你在哪個平臺上?這個例子是否真的代表了你在真實程序中所做的事情? – dano

回答

4

要考慮的一件事是CPython的線程實現。由於所謂的Global Interpreter Lock - GIL,Python中沒有真正的並行性(您可以在https://wiki.python.org/moin/GlobalInterpreterLock找到更多信息)。

這意味着,由於需要在這些線程及其串行運行時間之間進行上下文切換,因此在任務上運行更多線程實際上可能會導致更糟的性能結果。

如果你想要一個真正的加速,你可以使用不同的Python實現支持並行處理(比如Jython)或者查看multiprocessing模塊。

我修改您的代碼,得到的運行時間爲各種實施方式的示例:

2.47829794884 # serial port scan 
2.47367095947 # threaded port scan 
0.693325996399 # port scan using multiprocessing 

的結果是來自Fedora的20,4核CPU膝上型掃描40000個端口(或每個線程10000個端口/過程

+0

線程性能比無螺紋性能差得多,特別是如果OP主要在線程中進行I/O操作的話。看起來好像還有更多的事情不只是GIL在這裏。 – dano

+0

區別不在於* *大 - 對於1000個端口7-8秒將產生4000-端口28-32秒。 IO的數量也很小,因爲它只是打開和關閉套接字。 – mpolednik