操做系統/應用程序、操做中的「併發」、線程和進程的區別,線程

 

 

併發編程前言:python

      一、網絡應用程序員

           1)爬蟲 直接應用併發編程;django

           2)網絡框架 django flask tornado 源碼-併發編程編程

           3)socketserver 源碼-併發編程flask

      二、運維領域安全

           1)自動化開發-運維開發(機器的批量管理,任務的批量執行等)網絡

1、操做系統/應用程序多線程

a、硬件併發

       - 硬盤app

       - CPU

       - 主板

       - 顯卡

       - 內存

       - 電源

       . . . . . .

b、裝系統(軟件)

       - 系統就是一個由程序員寫出來的軟件,該軟件用於控制計算機的硬件,讓他們之間進行相互配合。

c、安軟件(安裝應用程序)

       - QQ

       - 百度雲

       - pycharm

       . . . . . .

2、並行與併發

  

併發:是僞並行,即看起來是同時運行。單個cpu+多道技術就能夠實現併發,(並行也屬於併發)

  單cpu,多進程併發舉例

 

  並行:並行:同時運行,只有具有多個cpu才能實現並行

  多個cpu、多進程並行舉例

 

3、線程和進程

a、單進程、單線程的應用程序,好比:

  print('666')

b、到底什麼是線程?什麼是進程?

       python本身沒有這玩意,python中調用的操做系統的線程和進程。

c、單進程、多線程的應用程序,好比:

 

    import threading
    print('666')

    def func(arg):
        print(arg)
    t = threading.Thread(target=func,args=(11,)) # 建立一個線程
    t.start()

  一個應用程序(軟件),能夠有多個進程(默認只有一個),一個進程中能夠建立多個線程(默認一個)。

 

問題1:爲何有這把GIL鎖?

              python語言的創始人在開發這門語言時,目的是快速把語言開發出來,若是加上GIL鎖(c語言加鎖),切換時按照100條字節指令來進行線程間的切換。

       問題2:進程和線程的區別?

              線程,線程是cpu工做的最小單元;

              進程,進程是cpu資源分配的最小單元,爲線程提供一個資源共享的空間;

              一個進程中能夠有多個線程,一個進程中默認有一個主線程;

              對於python來講,它的進程和線程和其餘語言有差別,有GIL鎖。它保證一個進程中同一時刻只有一個線程被cpu調度;

              IO密集型操做可使用多線程,計算密集型可使用多進程;

  問題3:線程建立的越多越好嗎?

              不是,線程之間進行切換,要作上下文管理。

 線程和進程的效率對比:線程的效率很是高,而且線程開啓不須要消耗什麼資源

 線程的建立

   第一中建立方式:

threading四ruai頂      Thread死ruai的

import time
from threading import Thread
from multiprocessing import Process
def func(n):
    print(n)

if __name__ == '__main__':
    # t = Thread(target=func,args=('我是線程',))
    # t.start() #速度很是快
    p = Process(target=func,args=('我是進程',))
    p.start()
    print('主線程結束') 

  第二種建立方式: 函數繼承Thread

class MyThread(Thread):

    def run(self):
        print('sb明傑')

if __name__ == '__main__':
    t = MyThread()
    t.start()
    print('主線程結束')

  

同一進程下,線程是資源共享的

import time
from threading import Thread
from multiprocessing import Process

num = 100
def func():
    global num
    num = 0

if __name__ == '__main__':
    t = Thread(target=func,)
    t.start()
    t.join()
    print(num)

  

 線程資源共享數據不安全,經過鎖來解決數據不安全的問題,線程模塊裏面引入的鎖

鎖(同步鎖\互斥鎖):保證數據安全,可是犧牲了效率,同步執行鎖內的代碼

import time
from threading import Thread,Lock          Lock(拉客)
num = 100
def func(t_lock):
    global num
    # num -= 1
    t_lock.acquire()
    mid = num
    mid = mid - 1
    time.sleep(0.0001)
    num = mid
    t_lock.release()
if __name__ == '__main__':
    t_lock = Lock() #鎖對象(同步鎖,互斥鎖)
    t_list = []
    for i in range(10):
        t = Thread(target=func,args=(t_lock,))
        t.start()
        t_list.append(t)
    [tt.join() for tt in t_list]

    print('主線程>>>',num)  

 解決死鎖線程,用遞歸鎖

互相搶到了對方的須要的鎖,致使雙方相互等待,程序無法進行

import time
from threading import Thread,Lock,RLock  #遞歸鎖

class MyThread(Thread):

    def __init__(self,lockA,lockB):
        super().__init__()
        self.lockA = lockA
        self.lockB = lockB

    def run(self):
        self.f1()
        self.f2()
    def f1(self):

        self.lockA.acquire()
        print('我拿了A鎖')

        self.lockB.acquire()
        print('我是一個很好的客戶!')
        self.lockB.release()

        self.lockA.release()

    def f2(self):
        self.lockB.acquire()
        time.sleep(0.1)
        print('我拿到了B鎖')
        self.lockA.acquire()
        print('我是一名合格的技師')
        self.lockA.release()

        self.lockB.release()


if __name__ == '__main__':
    # lockA = Lock()
    # lockB = Lock()
    # lockA = lockB = Lock() #不要這麼寫,別本身玩本身,鎖本身
    lockA = lockB = RLock()

    t1 = MyThread(lockA,lockB)
    t1.start()

    t2 = MyThread(lockA,lockB)
    t2.start()

    print('我是經理')  

 線程進程效率對比

 

import time
from threading import Thread
from multiprocessing import Process

def func(n):
    num = 0
    for n1 in range(n):
        num += n1
    print('num',num)
if __name__ == '__main__':
    t_s_t = time.time()
    t_list = []
    for i in range(10):
        t = Thread(target=func,args=(10,))
        t.start() #速度很是快
        t_list.append(t)
    [tt.join() for tt in t_list]
    t_e_t = time.time()
    t_dif_t = t_e_t - t_s_t  #獲取了線程的執行時間

    p_s_t = time.time() #開始時間
    p_list = []
    for ii in range(10):
        p = Process(target=func,args=(10,))
        p.start()
        p_list.append(p)
    [pp.join() for pp in p_list]
    p_e_t = time.time() #結束時間
    p_dif_t = p_e_t - p_s_t #時間差

    print('線程>>>>',t_dif_t)
    print('進程....',p_dif_t)
    print('主線程結束')  

 信號量

   信號量:控制同時可以進入鎖內去執行代碼的線程數量(進程數量),維護了一個計數器,剛開始建立信號量的時候假如設置的是4個房間,進入一次acquire就加一,出來一次就減一,若是計數器爲0的時候,才能夠繼續搶鑰匙,這樣其餘任務等待,這樣的話,其餘任務都是同步的狀態,而進入acquire裏面去執行的那四個任務是異步執行的

import time
from threading import Thread, Semaphore

def func1(s):
    s.acquire()
    time.sleep(1)
    print('大寶劍!!!')
    s.release()

if __name__ == '__main__':
    s = Semaphore(4)
    for i in range(10):
        t = Thread(target=func1,args=(s,))
        t.start() 

 主線程等待子線程的緣由

 

import time
from threading import Thread
from multiprocessing import Process

def func(n):
    time.sleep(5)
    print(n)


if __name__ == '__main__':
    # 主線程等待的是子線程的任務所有執行完畢
    t = Thread(target=func, args=('我是子線程',))
    t.start()  # 速度很是快

    # 主進程等待的是給子進程收屍
    # p = Process(target=func,args=('我是子進程',))
    # p.start()
    # print('主進程結束!!')
    print('主線程結束')

守護線程 

  主線程等待全部非守護進程的結束才結束,主線程的代碼運行結束,還要等待守護線的執行完畢,這個過程當中守護線程還存在

守護進程

  主進程代碼結束程序並無結束,而且主進程還存在,進程等待其餘的子進程執行結束之後,爲子進程收屍,注意一個問題:主進程的代碼運行結束守護進程跟着結束,

代碼以下

 

import time
from threading import Thread
from multiprocessing import Process

def func1(n):
    time.sleep(5)
    print(n)
def func2(n):
    time.sleep(3)
    print(n)

if __name__ == '__main__':
    # 進程
    p1 = Process(target=func1,args=('我是子進程1號',))
    p1.daemon = True  #設置守護,在start以前加
    p1.start()
    p2 = Process(target=func2, args=('我是子進程2號',))
    p2.start()

    t1 = Thread(target=func1, args=('我是子xiancheng1號',))
    t1.daemon = True
    t1.start()
    t2 = Thread(target=func2, args=('我是子xiancheng2號',))
    t2.start()

    print('主進程結束!!')
    print('主線程結束')

 

線程的其餘方法 1

from threading import Thread
import threading
import time
from multiprocessing import Process
import os

def work():
    import time
    time.sleep(1)
    # print('子線程',threading.get_ident()) #2608

if __name__ == '__main__':
    #在主進程下開啓線程
    t=Thread(target=work)    #死如唉的
    t.start()
            current_thread(扣的死如愛的)
    print(threading.current_thread())#主線程對象 #<_MainThread(MainThread, started 1376)>    
    print(threading.current_thread().getName()) #主線程名稱 #MainThread
    print(threading.current_thread().ident) #主線程ID #1376
    print(threading.get_ident()) #主線程ID #1376

    time.sleep(3)
    print(threading.enumerate())  # 連同主線程在內有兩個運行的線程,        enumerate枚舉(額牛木蕊特)
    print(threading.active_count()) # 2                   active_count(啊可特康特)
    print('主線程/主進程')

事件:

from threading import Thread,Event    Event(一溫特)

e = Event()  #e的狀態有兩種,False True,當事件對象的狀態爲False的時候,wait的地方會阻塞

e.set()  #將事件對象的狀態改成True
e.clear() #將事件對象的狀態改成Flase      clear(克雷爾)
print('在這裏等待')
e.wait() #阻塞                wait(威特)
print('還沒好!!')

  

線程隊列

隊列有三種模式

  先進先出:

import queue
q=queue.Queue()
q.put('first')
# q.put_nowait() #不等待
print(q.get())
q.get_nowait() #沒有數據就報錯,能夠經過try來搞       腦爲特

  先進後出:

import queue
q=queue.LifoQueue() #隊列,相似於棧,棧咱們提過嗎,是否是先進後出的順序啊
q.put('third')
print(q.get())

  優先級隊列:

import queue

q=queue.PriorityQueue()
#put進入一個元組,元組的第一個元素是優先級(一般是數字,也能夠是非數字之間的比較),數字越小優先級越高
q.put((-10,'a'))
q.put((-5,'a'))  #負數也能夠
q.put((20,'ws'))  #若是兩個值的優先級同樣,那麼按照後面的值的acsii碼順序來排序,若是字符串第一個數元素相同,比較第二個元素的acsii碼順序
q.put((20,'wd'))
q.put((20,{'a':11})) #TypeError: unorderable types: dict() < dict() 不能是字典
q.put((20,('w',1)))  #優先級相同的兩個數據,他們後面的值必須是相同的數據類型才能比較,能夠是元祖,也是經過元素的ascii碼順序來排序

'''
結果(數字越小優先級越高,優先級高的優先出隊):
'''  

線程池:

import time

from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
from threading import current_thread

def func(n):
    time.sleep(1)
    # print(n,current_thread().ident)
    return n**2

if __name__ == '__main__': 
    t_p = ThreadPoolExecutor(max_workers = 4)        max_workers(馬克思我K兒死)
    map_res = t_p.map(func,range(10)) #異步執行的,map自帶join功能
    print(map_res)
    print([i for i in map_res])

  

回調函數:

import time
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
from threading import current_thread

def func(n):
    time.sleep(1)
    print(n,current_thread().getName())
    return n**2

def func2(n):
    print('>>>>>>>',n.result())

if __name__ == '__main__':
    t_p = ThreadPoolExecutor(max_workers = 4)
    for i in range(3):
        t_p.submit(func,i).add_done_callback(func2)    add_done_callback(俺的 當 考班可)

    print('主線程結束')  

線程池的一些其餘方法: 

ThreadPoolExecutor(死日無愛的  噗奧  A克賽K特)

ProcessPoolExecutor(噗賽死  噗奧  A克賽K特)

import time
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
from threading import current_thread

def func(n):
    time.sleep(1)
    # print(n,current_thread().ident)
    return n**2
if __name__ == '__main__':
    t_p = ThreadPoolExecutor(max_workers = 4)
    t_res_list = []
    for i in range(10): 
        res_obj = t_p.submit(func,i)#異步提交了10個任務,submit(色賣特)
        t_res_list.append(res_obj)

    t_p.shutdown()  #close + join    shutdown(莎當)        close(可簍子)
    for e_res in t_res_list:
        print(e_res.result())#他和get同樣  result(蕊造特) 

 多線程和多進程進行純計算的效率

import time
from multiprocessing import Process
from threading import Thread

def func():
    num = 0
    for i in range(1,10000000):
        num += i

# def func():
#     time.sleep(2)
#     print('xxxxxxxx')

if __name__ == '__main__':
    p_s_t = time.time()
    p_list = []
    for i in range(10):
        p = Process(target=func,)
        p_list.append(p)
        p.start()
    [pp.join() for pp in p_list]
    p_e_t = time.time()
    p_dif_t = p_e_t - p_s_t

    t_s_t = time.time()
    t_list = []
    for i in range(10):
        t = Thread(target=func,)
        t_list.append(t)
        t.start()
    [tt.join() for tt in t_list]
    t_e_t = time.time()
    t_dif_t = t_e_t - t_s_t

    print('多進程執行的時間',p_dif_t)
    print('多線程執行的時間',t_dif_t)

'''
多進程執行的時間 4.5982630252838135
多線程執行的時間 8.339477062225342
'''
運算

GIL鎖:

 

併發執行的效率(在沒有IO的狀況下,兩個純計算的任務 )

import time
def func1():
    num2 = 0
    for i in range(1000001):
        num2 += i
        yield
        # print('執行到下一個yield',current_thread().name)

def func2():
    g = func1()
    next(g)
    sum = 0
    for i in range(1000000):
        # g.send(i)
        sum += i
        next(g)
s_t = time.time()
func2()
print('協程的時間',time.time() - s_t)  

 串行執行的效率

def func1():
    num2 = 0
    for i in range(1000001):
        num2 += i
        # print('執行到下一個yield',current_thread().name)

def func2():
    sum = 0
    for i in range(1000000):
        sum = sum + i


s_t = time.time()
func1()
func2()
print('串行的時間',time.time() - s_t)

'''
協程的時間 0.319796085357666
串行的時間 0.14291739463806152
'''
相關文章
相關標籤/搜索