並發編程之多線程

來源:互聯網
上載者:User

標籤:子進程   sleep   空間   import   執行   setname   python   roc   oba   

一、並發編程之多線程

1、線程簡單介紹

進程是資源單位,把所有資源集中到一起,而線程是執行單位,真正執行的是線程

每個進程都有一個地址空間,而且預設就有一個控制線程

多線程:在一個進程中存在多個控制線程,多個控制線程共用該進程的地址空間。進程之間是競爭關係,線程之間是協作關係

線程的建立開銷比進程小很多,運行較快

主線程從執行層面上代表了其所在進程的執行過程

 

2、線程開啟方式

方式一:使用替換threading模組提供的Thread

 from threading import Thread
 
 def task():
   print(‘is running‘)

 if __name__ == ‘__main__‘:
   t=Thread(target=task,)
   t.start()
   print(‘主‘)

 

方式二:自訂類,繼承Thread

from threading import Thread
class MyThread(Thread):
  def __init__(self,name):
    super().__init__()
    self.name=name
  def run(self):
    print(‘%s is running‘ %self.name)

if __name__ == ‘__main__‘:
  t=MyThread(‘egon‘)
  t.start()
  print(‘主‘)

 

3、線程與進程的pid

from threading import Thread
from multiprocessing import Process
import os

def task():
  print(‘%s is running‘ %os.getpid())

if __name__ == ‘__main__‘:
  # t1=Thread(target=task,)      #在主進程下開啟多個線程,每個線程都跟主進程的pid一樣
  # t2=Thread(target=task,)
  t1=Process(target=task,)     #開啟多個進程,每個進程都有不同的pid
  t2=Process(target=task,)
  t1.start()
  t2.start()
  print(‘主‘,os.getpid())

 

4、多線程共用同一個進程內的資源

from threading import Thread
from multiprocessing import Process
n=100
def work():
  global n
  n=0

if __name__ == ‘__main__‘:

  # p=Process(target=work,)        
  # p.start()
  # p.join()
  # print(‘主‘,n)                 #子進程p已經將自己的全域的n改成了0,但改的是它自己的,父進程仍然是100

  t=Thread(target=work,)
  t.start()
  t.join()
  print(‘主‘,n)                    #查看結果為0,同一進程內的線程之間共用進程內的資料

 

5、Thread對象其他相關的屬性或方法

isAlive():返回線程是否活動

getName():返回線程名

setName():設定線程名

 current_thread的用法
 from threading import Thread,activeCount,enumerate,current_thread
 from multiprocessing import Process
 import time

 def task():
   print(‘%s is running‘ %current_thread().getName())
   time.sleep(2)

 if __name__ == ‘__main__‘:
   p=Process(target=task)
   p.start()
   print(current_thread())

 

6、守護線程

進程跟線程都會遵循:守護xxx會等待主xxx運行完畢後被銷毀

主進程:運行完畢指的是主進程代碼運行完畢

主線程:運行完畢指的是主線程所在的進程內所有非守護線程統統運行完畢,主線程才算運行完畢

注意:運行完畢並非終止運行

from threading import Thread
import time

def task1():
  print(‘123‘)
  time.sleep(10)
  print(‘123done‘)

def task2():
  print(‘456‘)
  time.sleep(1)
  print(‘456done‘)

if __name__ == ‘__main__‘:
  t1=Thread(target=task1)
  t2=Thread(target=task2)
  t1.daemon=True
  t1.start()
  t2.start()
  print(‘主‘)

 

7、GIL全域解譯器鎖

GIL本質是一把互斥鎖,將並發運行變成串列,以此來控制同一時間內共用資料只能被一個任務所修改,進而保證資料安全。

在Cpython解譯器中,同一個進程下開啟的多線程,同一時刻只能有一個線程執行,無法利用多核優勢

from threading import Thread
n=100
  def task():
    print(‘is running‘)

if __name__ == ‘__main__‘:
  t1=Thread(target=task,)
  t2=Thread(target=task,)
  t3=Thread(target=task,)
  # t=Process(target=task,)
  t1.start()
  t2.start()
  t3.start()
  print(‘主‘)

多個線程先訪問到解譯器的代碼,即拿到執行許可權,然後將target的代碼交給解譯器的代碼去執行

解譯器的代碼是所有線程共用的,所以記憶體回收線程也可能訪問到解譯器的代碼而去執行,這就導致了一個問題:對於同一個資料100,可能線程1執行n=100的同時,而記憶體回收執行的是回收100的操作,解決這種問題沒有什麼高明的方法,就是加鎖處理,如的GIL,保證python解譯器同一時間只能執行一個任務的代碼

結論:

1、如果是I/O密集型的,可以開啟多線程

2、如果是要求計算效能,可以利用多核,開啟進程

 

 

8、同步鎖

1、線程搶的是CIL鎖,GIL鎖相當於執行許可權,拿到執行許可權後才能拿到互斥鎖lock,其他線程也可以搶到GIL,但如果發現lock仍然沒有被釋放則阻塞,即便是拿到執行許可權GIL也要立刻交出來

2、jion是等待所有,即整體串列,而鎖只是鎖住修改共用資料的部分,即部分串列,要想保住資料安全性的根本原來在於讓並發變成串列,jion與互斥鎖都可以實現,互斥鎖的部分串列效率更高

並發編程之多線程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.