❶ 為什麼有人說 python 的多線程是雞肋

Python多線程是不是雞肋,是,GIL那個東西再那裡擺著,就算在多核下面Python也是無法並行的,這個好理解嘛,就相當於做了個分時復用。
Python多線程有沒有用,有,你去爬圖片站的時候,用單進程單線程這種方式,進程很容易阻塞在獲取數據socket函數上,多線程可以緩解這種情況。你說解決沒有,要是每個請求都阻塞起了,那多線程也沒什麼用(當然,這種情況沒見過哈)。
Python的優勢就在於寫起來快,用起來方便。你要做計算密集型的,還想並行化的話,還是用C吧。

❷ python多進程,多線程分別是並行還是並發

並發和並行

你吃飯吃到一半,電話來了,你一直到吃完了以後才去接,這就說明你不支持並發也不支持並行。
你吃飯吃到一半,電話來了,你停了下來接了電話,接完後繼續吃飯,這說明你支持並發。
你吃飯吃到一半,電話來了,你一邊打電話一邊吃飯,這說明你支持並行。
並發的關鍵是你有處理多個任務的能力,不一定要同時。
並行的關鍵是你有同時處理多個任務的能力。
所以我認為它們最關鍵的點就是:是否是『同時』。
Python 中沒有真正的並行,只有並發
無論你的機器有多少個CPU, 同一時間只有一個Python解析器執行。這也和大部分解釋型語言一致, 都不支持並行。這應該是python設計的先天缺陷。
javascript也是相同的道理, javascript早起的版本只支持單任務,後來通過worker來支持並發。
Python中的多線程
先復習一下進程和線程的概念
所謂進程,簡單的說就是一段程序的動態執行過程,是系統進行資源分配和調度的一個基本單位。一個進程中又可以包含若干個獨立的執行流,我們將這些執行流稱為線程,線程是CPU調度和分配的基本單位。同一個進程的線程都有自己的專有寄存器,但內存等資源是共享的。
這里有一個更加形象的解釋, 出自阮一峰大神的傑作:
http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html
Python中的thread的使用
通過 thread.start_new_thread 方法
import thread
import time

# Define a function for the thread
def print_time( threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print "%s: %s" % ( threadName, time.ctime(time.time()) )

# Create two threads as follows
try:
thread.start_new_thread( print_time, ("Thread-1", 2, ) )
thread.start_new_thread( print_time, ("Thread-2", 4, ) )
except:
print "Error: unable to start thread"

while 1:
pass

通過繼承thread
#!/usr/bin/python
import threading
import time
exitFlag = 0
class myThread (threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print "Starting " + self.name
print_time(self.name, self.counter, 5)
print "Exiting " + self.name

def print_time(threadName, delay, counter):
while counter:
if exitFlag:
threadName.exit()
time.sleep(delay)
print "%s: %s" % (threadName, time.ctime(time.time()))
counter -= 1

# Create new threads
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)

# Start new Threads
thread1.start()
thread2.start()
print "Exiting Main Thread"

線程的同步
#!/usr/bin/python

import threading
import time

class myThread (threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print "Starting " + self.name
# Get lock to synchronize threads
threadLock.acquire()
print_time(self.name, self.counter, 3)
# Free lock to release next thread
threadLock.release()

def print_time(threadName, delay, counter):
while counter:
time.sleep(delay)
print "%s: %s" % (threadName, time.ctime(time.time()))
counter -= 1

threadLock = threading.Lock()
threads = []

# Create new threads
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)

# Start new Threads
thread1.start()
thread2.start()

# Add threads to thread list
threads.append(thread1)
threads.append(thread2)

# Wait for all threads to complete
for t in threads:
t.join()
print "Exiting Main Thread"

利用multiprocessing多進程實現並行
進程的創建
Python 中有一套類似多線程API 的的類來進行多進程開發: multiprocessing
這里是一個來自官方文檔的例子:
from multiprocessing import Process
def f(name):
print 'hello', name

if __name__ == '__main__':
p = Process(target=f, args=('bob',))
p.start()
p.join()

類似與線程,一可以通過繼承process類來實現:
from multiprocessing import Process
class Worker(Process):
def run(self):
print("in" + self.name)

if __name__ == '__main__':
jobs = []
for i in range(5):
p = Worker()
jobs.append(p)
p.start()
for j in jobs:
j.join()

進程的通信
Pipe()
pipe()函數返回一對由雙向通信的管道連接的對象,這兩個對象通過send, recv 方法實現 信息的傳遞
from multiprocessing import Process, Pipe

def f(conn):
conn.send([42, None, 'hello'])
conn.close()

if __name__ == '__main__':
parent_conn, child_conn = Pipe()
p = Process(target=f, args=(child_conn,))
p.start()
print parent_conn.recv() # prints "[42, None, 'hello']"
p.join()

Quene
from multiprocessing import Process, Queue
def f(q):
q.put([42, None, 'hello'])

if __name__ == '__main__':
q = Queue()
p = Process(target=f, args=(q,))
p.start()
print q.get() # prints "[42, None, 'hello']"
p.join()

進程間的同步
Python 中多進程中也有類似線程鎖的概念,使用方式幾乎一樣:
from multiprocessing import Process, Lock
def f(l, i):
l.acquire()
print 'hello world', i
l.release()
if __name__ == '__main__':
lock = Lock()
for num in range(10):
Process(target=f, args=(lock, num)).start()

進程間的共享內存
每個進程都有獨自的內存,是不能相互訪問的, 也行 python官方覺得通過進程通信的方式過於麻煩,提出了共享內存的概念,以下是官方給出的例子:
from multiprocessing import Process, Value, Array

def f(n, a):
n.value = 3.1415927
for i in range(len(a)):
a[i] = -a[i]

if __name__ == '__main__':
num = Value('d', 0.0)
arr = Array('i', range(10))

p = Process(target=f, args=(num, arr))
p.start()
p.join()

print num.value
print arr[:]

總結
python通過多進程實現多並行,充分利用多處理器,彌補了語言層面不支持多並行的缺點。Python, Node.js等解釋型語言似乎都是通過這種方式來解決同一個時間,一個解釋器只能處理一段程序的問題, 十分巧妙。

❸ python中什麼是線程

線程是系統中的名詞,Python一般是單線程的,Python的多線程優化很差。
線程,有時被稱為輕量級進程(Lightweight Process,LWP),是程序執行流的最小單元。一個標準的線程由線程ID,當前指令指針(PC),寄存器集合和堆棧組成。另外,線程是進程中的一個實體,是被系統獨立調度和分派的基本單位,線程自己不擁有系統資源,只擁有一點兒在運行中必不可少的資源,但它可與同屬一個進程的其它線程共享進程所擁有的全部資源。一個線程可以創建和撤消另一個線程,同一進程中的多個線程之間可以並發執行。由於線程之間的相互制約,致使線程在運行中呈現出間斷性。線程也有就緒、阻塞和運行三種基本狀態。就緒狀態是指線程具備運行的所有條件,邏輯上可以運行,在等待處理機;運行狀態是指線程佔有處理機正在運行;阻塞狀態是指線程在等待一個事件(如某個信號量),邏輯上不可執行。每一個程序都至少有一個線程,若程序只有一個線程,那就是程序本身。
線程是程序中一個單一的順序控制流程。進程內有一個相對獨立的、可調度的執行單元,是系統獨立調度和分派CPU的基本單位指令運行時的程序的調度單位。在單個程序中同時運行多個線程完成不同的工作,稱為多線程。

❹ python線程間通信的問題,回答有加分!300

pyqt的線程之間的通信是通過信號to槽來實現的,首先你在線程類裡面聲明一個全局槽比如:

classimThread(QtCore.QThread):
imslot=QtCore.pyqtSignal()

這里是要重點注意,上面的是沒有任何參數的一個信號,如果你需要參數的話,你可以在裡面添加參數類型,例如:

imslot1=QtCore.pyqtSignal(str)#這是一個帶字元串參數的信號
imslot2=QtCore.pyqtSignal(int)#這是一個帶整型參數的信號
imslot3=QtCore.pyqtSignal(bool)#這是一個帶布爾參數的信號

當然了,如果你需要多個參數的話,同樣地往裡面加就是了,qt也沒有要求參數必須是同類型的,所以可以這樣:

imslot1=QtCore.pyqtSignal(str,int)#這是一個帶整型和字元串的參數信號
imslot2=QtCore.pyqtSignal(int,str,str)#這是一個帶整型和兩個字元串的參數信號
imslot3=QtCore.pyqtSignal(bool,str)#這是一個帶布爾和字元串的參數信號

在線程的run方法裡面來定義執行信號:

self.imslot.emit()

這里也是需要重點注意的是,上面這個介面是沒有參數的,如果你是要參數的話,是需要這樣寫:

self.imslot1[str].emit('hello')
self.imslot2[int].emit(1)
self.imslot3[bool].emit(False)

多參數的是這樣

self.imslot1[str,int].emit('hello',1)
self.imslot2[int,str,str].emit(1,"hello","world")
self.imslot3[bool,str].emit(False,'hello')

以上就是在線程類裡面完成信號定義了,接下來就是邏輯層成定義一個函數槽來連接線程類裡面的信號,這個也很簡單,比如我在主線程類裡面定義一個方法:

defimSlot():
print'ok'

以上這個是槽函數,接下來是實現信號槽的連接

imThread.imslot.connect('imSlot')

這個就是信號槽的連接方式,當然了,這個是沒有參數的一個信號槽,那麼帶參數的怎麼寫呢?也很簡單!首先定義一個槽函數:

defimSlot(para):
printpara

這個是帶參數的槽函數,下面是:

imThread.imslot[str].connect('imSlot')

以上就是線程之間的方法了,子線程在執行的通行經過執行信號的話,子線程可以安全地執行而不會出現GUI主線程卡死的情況了。

❺ PYTHON多線程同步的幾種方法

Python進階(二十六)-多線程實現同步的四種方式
臨界資源即那些一次只能被一個線程訪問的資源,典型例子就是列印機,它一次只能被一個程序用來執行列印功能,因為不能多個線程同時操作,而訪問這部分資源的代碼通常稱之為臨界區。
鎖機制
threading的Lock類,用該類的acquire函數進行加鎖,用realease函數進行解鎖
import threadingimport timeclass Num:
def __init__(self):
self.num = 0
self.lock = threading.Lock() def add(self):
self.lock.acquire()#加鎖,鎖住相應的資源
self.num += 1
num = self.num
self.lock.release()#解鎖,離開該資源
return num

n = Num()class jdThread(threading.Thread):
def __init__(self,item):
threading.Thread.__init__(self)
self.item = item def run(self):
time.sleep(2)
value = n.add()#將num加1,並輸出原來的數據和+1之後的數據
print(self.item,value)for item in range(5):
t = jdThread(item)
t.start()
t.join()#使線程一個一個執行

當一個線程調用鎖的acquire()方法獲得鎖時,鎖就進入「locked」狀態。每次只有一個線程可以獲得鎖。如果此時另一個線程試圖獲得這個鎖,該線程就會變為「blocked」狀態,稱為「同步阻塞」(參見多線程的基本概念)。
直到擁有鎖的線程調用鎖的release()方法釋放鎖之後,鎖進入「unlocked」狀態。線程調度程序從處於同步阻塞狀態的線程中選擇一個來獲得鎖,並使得該線程進入運行(running)狀態。
信號量
信號量也提供acquire方法和release方法,每當調用acquire方法的時候,如果內部計數器大於0,則將其減1,如果內部計數器等於0,則會阻塞該線程,知道有線程調用了release方法將內部計數器更新到大於1位置。
import threadingimport timeclass Num:
def __init__(self):
self.num = 0
self.sem = threading.Semaphore(value = 3) #允許最多三個線程同時訪問資源

def add(self):
self.sem.acquire()#內部計數器減1
self.num += 1
num = self.num
self.sem.release()#內部計數器加1
return num

n = Num()class jdThread(threading.Thread):
def __init__(self,item):
threading.Thread.__init__(self)
self.item = item def run(self):
time.sleep(2)
value = n.add()
print(self.item,value)for item in range(100):

❻ 為什麼有人說Python的多線程是雞肋

因為 Python 中臭名昭著的 GIL。

那麼 GIL 是什麼?為什麼會有 GIL?多線程真的是雞肋嗎? GIL 可以去掉嗎?帶著這些問題,我們一起往下看,同時需要你有一點點耐心。

多線程是不是雞肋,我們先做個實驗,實驗非常簡單,就是將數字 「1億」 遞減,減到 0 程序就終止,這個任務如果我們使用單線程來執行,完成時間會是多少?使用多線程又會是多少?show me the code

那麼把 GIL 去掉可行嗎?

還真有人這么干多,但是結果令人失望,在1999年Greg Stein 和Mark Hammond 兩位哥們就創建了一個去掉 GIL 的 Python 分支,在所有可變數據結構上把 GIL 替換為更為細粒度的鎖。然而,做過了基準測試之後,去掉GIL的 Python 在單線程條件下執行效率將近慢了2倍。

Python之父表示:基於以上的考慮,去掉GIL沒有太大的價值而不必花太多精力。

❼ python可以獲取其他線程嗎可以獲取其他線程中的對象嗎

可以的,你可以利用線程間通信來獲取其他線程的信息和對象。

❽ python多線程怎樣同步

鎖機制
�6�9�6�9threading的Lock類,用該類的acquire函數進行加鎖,用realease函數進行解鎖

import threading
import time

class Num:
def __init__(self):
self.num = 0
self.lock = threading.Lock()
def add(self):
self.lock.acquire()#加鎖,鎖住相應的資源
self.num += 1
num = self.num
self.lock.release()#解鎖,離開該資源
return num

n = Num()
class jdThread(threading.Thread):
def __init__(self,item):
threading.Thread.__init__(self)
self.item = item
def run(self):
time.sleep(2)
value = n.add()#將num加1,並輸出原來的數據和+1之後的數據
print(self.item,value)

for item in range(5):
t = jdThread(item)
t.start()
t.join()#使線程一個一個執行
�6�9�6�9當一個線程調用鎖的acquire()方法獲得鎖時,鎖就進入「locked」狀態。每次只有一個線程可以獲得鎖。如果此時另一個線程試圖獲得這個鎖,該線程就會變為「blocked」狀態,稱為「同步阻塞」(參見多線程的基本概念)。
�6�9�6�9直到擁有鎖的線程調用鎖的release()方法釋放鎖之後,鎖進入「unlocked」狀態。線程調度程序從處於同步阻塞狀態的線程中選擇一個來獲得鎖,並使得該線程進入運行(running)狀態。

信號量
�6�9�6�9信號量也提供acquire方法和release方法,每當調用acquire方法的時候,如果內部計數器大於0,則將其減1,如果內部計數器等於0,則會阻塞該線程,知道有線程調用了release方法將內部計數器更新到大於1位置。

import threading
import time
class Num:
def __init__(self):
self.num = 0
self.sem = threading.Semaphore(value = 3)
#允許最多三個線程同時訪問資源

def add(self):
self.sem.acquire()#內部計數器減1
self.num += 1
num = self.num
self.sem.release()#內部計數器加1
return num

n = Num()
class jdThread(threading.Thread):
def __init__(self,item):
threading.Thread.__init__(self)
self.item = item
def run(self):
time.sleep(2)
value = n.add()
print(self.item,value)

for item in range(100):
t = jdThread(item)
t.start()
t.join()
條件判斷
�6�9�6�9所謂條件變數,即這種機制是在滿足了特定的條件後,線程才可以訪問相關的數據。
�6�9�6�9它使用Condition類來完成,由於它也可以像鎖機制那樣用,所以它也有acquire方法和release方法,而且它還有wait,notify,notifyAll方法。

"""
一個簡單的生產消費者模型,通過條件變數的控制產品數量的增減,調用一次生產者產品就是+1,調用一次消費者產品就會-1.
"""

"""
使用 Condition 類來完成,由於它也可以像鎖機制那樣用,所以它也有 acquire 方法和 release 方法,而且它還有
wait, notify, notifyAll 方法。
"""

import threading
import queue,time,random

class Goods:#產品類
def __init__(self):
self.count = 0
def add(self,num = 1):
self.count += num
def sub(self):
if self.count>=0:
self.count -= 1
def empty(self):
return self.count <= 0

class Procer(threading.Thread):#生產者類
def __init__(self,condition,goods,sleeptime = 1):#sleeptime=1
threading.Thread.__init__(self)
self.cond = condition
self.goods = goods
self.sleeptime = sleeptime
def run(self):
cond = self.cond
goods = self.goods
while True:
cond.acquire()#鎖住資源
goods.add()
print("產品數量:",goods.count,"生產者線程")
cond.notifyAll()#喚醒所有等待的線程--》其實就是喚醒消費者進程
cond.release()#解鎖資源
time.sleep(self.sleeptime)

class Consumer(threading.Thread):#消費者類
def __init__(self,condition,goods,sleeptime = 2):#sleeptime=2
threading.Thread.__init__(self)
self.cond = condition
self.goods = goods
self.sleeptime = sleeptime
def run(self):
cond = self.cond
goods = self.goods
while True:
time.sleep(self.sleeptime)
cond.acquire()#鎖住資源
while goods.empty():#如無產品則讓線程等待
cond.wait()
goods.sub()
print("產品數量:",goods.count,"消費者線程")
cond.release()#解鎖資源

g = Goods()
c = threading.Condition()

pro = Procer(c,g)
pro.start()

con = Consumer(c,g)
con.start()
同步隊列
�6�9�6�9put方法和task_done方法,queue有一個未完成任務數量num,put依次num+1,task依次num-1.任務都完成時任務結束。

import threading
import queue
import time
import random

'''
1.創建一個 Queue.Queue() 的實例,然後使用數據對它進行填充。
2.將經過填充數據的實例傳遞給線程類,後者是通過繼承 threading.Thread 的方式創建的。
3.每次從隊列中取出一個項目,並使用該線程中的數據和 run 方法以執行相應的工作。
4.在完成這項工作之後,使用 queue.task_done() 函數向任務已經完成的隊列發送一個信號。
5.對隊列執行 join 操作,實際上意味著等到隊列為空,再退出主程序。
'''

class jdThread(threading.Thread):
def __init__(self,index,queue):
threading.Thread.__init__(self)
self.index = index
self.queue = queue

def run(self):
while True:
time.sleep(1)
item = self.queue.get()
if item is None:
break
print("序號:",self.index,"任務",item,"完成")
self.queue.task_done()#task_done方法使得未完成的任務數量-1

q = queue.Queue(0)
'''
初始化函數接受一個數字來作為該隊列的容量,如果傳遞的是
一個小於等於0的數,那麼默認會認為該隊列的容量是無限的.
'''
for i in range(2):
jdThread(i,q).start()#兩個線程同時完成任務

for i in range(10):
q.put(i)#put方法使得未完成的任務數量+1

❾ python怎麼能同時執行代碼(多線程)

多線程不是這個意思。
普通的單線程,比如
代碼塊版A
循環代碼塊B
循環代碼塊C
代碼塊D
程序會按順權序A,B,C,D這樣執行,而B循環如果沒有結束,C循環不會開始。
如果是多線程,
代碼塊A
新線程:循環代碼塊B
循環代碼塊C
代碼塊D
這樣,B循環新開一個線程運行,原來的線程會繼續運行C,B有沒有結束,不影響C