簡(jiǎn)述進(jìn)程妹田,線程和協(xié)程

線程,進(jìn)程和協(xié)程

線程

線程的概念

并發(fā)

任務(wù)數(shù)大于cpu核載,通過(guò)系統(tǒng)的各種任務(wù)跳讀算法,是任務(wù)“在一起”執(zhí)行任務(wù)唬党! 假的多任務(wù)

并行

任務(wù)數(shù)小于cpu核數(shù)鹃共,即任務(wù)真的在一起執(zhí)行

多線程

1 同時(shí)執(zhí)行

下面例子中test1和test2是同時(shí)執(zhí)行

import threading
import time

def tes1():
    for i in range(3):
        print("--test1--%d" % i)
        time.sleep(1)
        
def tes2():
    for i in range(3):
        print("--test2--%d" % i)
        time.sleep(1)
        
if __name__ == "__main__":
    t1 = threading.Thread(target=test1)
    t2 = threading.Thread(target=test2)
    
    t1.start()  # 啟動(dòng)線程,讓線程開(kāi)始執(zhí)行
    t2.start()
# 執(zhí)行結(jié)果
--test1--0
--test2--0
(間隔1秒)
--test1--1
--test2--1
(間隔1秒)
--test1--2
--test2--2

2 順序執(zhí)行

test1先執(zhí)行,test2后執(zhí)行

import threading
import time

def tes1():
    for i in range(3):
        print("--test1--%d" % i)
        
def tes2():
    for i in range(3):
        print("--test2--%d" % i)
        
if __name__ == "__main__":
    t1 = threading.Thread(target=test1)
    t2 = threading.Thread(target=test2)
    
    t1.start()
    time.sleep(1)
    print("test1 is over")
    
    t2.start()
    time.sleep(1)
    print("test2 is over")
    
# 執(zhí)行結(jié)果
--test1--0
--test1--1
--test1--2
(間隔1秒)
test1 over
--test2--0
--test2--1
--test2--2
(間隔1面)
test2 over

多線程全局變量

全局變量

import threading
import time

g_num = 100

def test1():
    global g_num
    g_num += 1
    print("--in test1 g_num=%d" % g_num)
    
def test2():
    print("--in test2 g_num=%d" % g_num)
    
if __name__ == "__main__":
    t1 = threading.Thread(target=test1)
    t2 = threading.Thread(target=test2)
    
    t1.start()
    time.sleep(1)
    
    t2.start()+
    time.sleep(1)

去函數(shù)那個(gè)筆記了解全局變量

多線程全局變量實(shí)參

import threading
import time

g_num = 100

def test1(temp): #傳遞實(shí)參的方式
    temp.append(33)
    print("--in test1 temp=%s" % str(temp))
    545.
def test2():
    print("--in test2 temp=%s" % str(temp))
g_num = [11,22]

if __name__ == "__main__":
    # 創(chuàng)建線程
    t1 = threading.Thread(target=test1, args=(g_num,)) 
    t2 = threading.Thread(target=test2, args=(g_num,))
    
    t1.start()
    time.sleep(1)
    
    t2.start()
    time.sleep(1)

多線程共享全局變量資源競(jìng)爭(zhēng)

import threading
import time

g_num = 0

def test1():
    glibal g_num
    for i in range(num):
        g_num += 1
    print("--in test1 g_num=%d" % g_num)
    
def test2():
    glibal g_num
    for i in range(num):
        g_num += 1
    print("--in test2 g_num=%d" % g_num)
    
if __name__ == "__main__":
    # 創(chuàng)建線程
    t1 = threading.Thread(target=test1,args=(100,))
    t2 = threading.Thread(target=test2,args=(100,))
    
    # t1 = threading.Thread(target=test1,args=(10000,))
    # t2 = threading.Thread(target=test2,args=(10000,))
    
    t1.start()
    t2.start()

多線程解決全局變量資源競(jìng)爭(zhēng)01

使用互斥鎖

import threading
import time

g_num = 0

def test1():
    glibal g_num
    # 上鎖,如果之前沒(méi)有上鎖,那么此時(shí)上鎖成功
    # 如果之前上過(guò)鎖,那么就會(huì)堵塞在這里,知道這個(gè)鎖解開(kāi)為止
    muext.acquire()
    for i in range(num):
        g_num += 1    
    # 解鎖
    muext.release()  
    print("--in test1 g_num=%d" % g_num)
                                   
def test2():
    glibal g_num
    muext.acquire()
    for i in range(num):
        g_num += 1
    muext.release()
    print("--in test2 g_num=%d" % g_num)
# 建立一個(gè)互斥鎖,默認(rèn)是沒(méi)有上鎖的
muext = threading.Lock()    

if __name__ == "__main__":
    
    t1 = threading.Thread(target=test1,args=(10000,))
    t2 = threading.Thread(target=test2,args=(10000,))
    
    t1.start()
    t2.start()
# 上述代碼上鎖和解鎖在for循環(huán)外,解釋:子線程t1和t2不知道誰(shuí)先執(zhí)行,假如是t1先執(zhí)行,在上鎖的后,一直執(zhí)行for循環(huán)驶拱,知道循環(huán)結(jié)束為止然后在解鎖霜浴,在執(zhí)行t2此時(shí)全局變量從0變成了10000,直到for循環(huán)結(jié)束解鎖變成2000,程序解鎖

多線程解決全局變量資源競(jìng)爭(zhēng)02

import threading
import time

g_num = 0

def test1():
    glibal g_num
    for i in range(num):
        muext.acquire()
        g_num += 1
        muext.release()
    print("--in test1 g_num=%d" % g_num)
    
def test2():
    glibal g_num
    for i in range(num):
        muext.acquire()
        g_num += 1
        muext.release()
    print("--in test2 g_num=%d" % g_num)

muext = threading.Lock()

if __name__ == "__main__":

    t1 = threading.Thread(target=test1,args=(10000,))
    t2 = threading.Thread(target=test2,args=(10000,))
    
    t1.start()
    t2.start()
# 如果上鎖和解鎖在for循環(huán)內(nèi)部蓝纲,不管t1和t2誰(shuí)先執(zhí)行阴孟,每次執(zhí)行+1結(jié)束后解鎖,然后在分配t1和t2誰(shuí)先執(zhí)行驻龟,這個(gè)先后是沒(méi)有規(guī)律的,可能是t1執(zhí)行很多次之后再是執(zhí)行t2温眉,可能反之,所以其中一個(gè)是for循環(huán)執(zhí)行結(jié)束后得到20000,但是另外一個(gè)一定是執(zhí)行10000后還在疊加

多任務(wù)版UDP聊天

import socket
import threading

if __name__ == "__main__":
    # 創(chuàng)建套接字
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 綁定端口
    udp_socket.bind(("", 7788))
    # 獲得對(duì)方ip和port
    dest_ip = input("請(qǐng)輸入ip:")
    dest_port = input("請(qǐng)輸入port:")
    # 接受數(shù)據(jù)
    while True:
        recv_data = udp_socket.recvfrom(1024)
        print(recv_data)
        
    # 發(fā)送數(shù)據(jù)
    while True:
        send_data = input("輸入數(shù)據(jù):")
        udp_socket.sendto(send_data.encode("utf-8"), dest_ip,dest_port)
        
# 利用多線程

import socket
import threading

def recv_msg(udp_socket):
    # 接受數(shù)據(jù)
    while True:
        recv_data = udp_socket.recvfrom(1024)
        #print(recv_data)
        print("[%s]:%s" %(recv_data[1], str(recv_data[0].decode("utf-8"))))
        # 顯示發(fā)送的對(duì)方地址和信息

def send_msg(udp_socket,dest_ip,dest_port):
    # 發(fā)送數(shù)據(jù)
    while True:
        send_data = input("輸入數(shù)據(jù):")
        udp_socket.sendto(send_data.encode("utf-8"), dest_ip,dest_port)


if __name__ == "__main__":
    # 創(chuàng)建套接字
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 綁定端口
    udp_socket.bind(("", 7788))
    # 獲得對(duì)方ip和port
    dest_ip = input("請(qǐng)輸入ip:")
    dest_port = int(input("請(qǐng)輸入port:"))  # 注意
    
    t_recv = threading.Thread(target=recv_msg, args=(udp_socket,))
    t_send = threading.Thread(target=send_msg, args=(udp_socket,dest_ip,dest_port))
    
    t_recv.start()
    t_send.start()

進(jìn)程

進(jìn)程的概念

一個(gè)程序運(yùn)行起來(lái),代碼+用到的資源稱之為進(jìn)程翁狐,他是操作系統(tǒng)分配資源的基本單位元

導(dǎo)入multiprocessing模塊

子進(jìn)程的傳遞參數(shù)

import multiprocessing
# import os  # 導(dǎo)入路徑模塊
import time

def test(a,b,c,*args, **kwargs):
    print(a)
    print(b)
    print(c)
    print(args)  # 拆包(元組)
    print(kwargs)  # 拆包(字典)

if __name__ == "__main__":
    p = multiprocessing.Process(target=test, args=(1,2,3,4,5,6,7,8), kwargs={"name":"Lily"})
    # 當(dāng)導(dǎo)入元素和元組的時(shí)候类溢,統(tǒng)一以元組的形式導(dǎo)入
    # 當(dāng)傳入kwargs的時(shí)候,在創(chuàng)建p類的時(shí)候,傳入字典形式
    
    p.start()

多進(jìn)程之間不共享全局變量

進(jìn)程之間是兩個(gè)獨(dú)立的程序不共享全局變量

import multiprocessing
import time

nums = [1,2,3]  #設(shè)定全局變量

def test1():
    nums.append(4)  # 利用方法改變?nèi)肿兞?    print("在test1中nums=%s" % str(nums))
    
def test2():
    print("在test2中nums=%s" % str(nums))
    
if __name__ == "__main__":
    # 創(chuàng)建進(jìn)程
    p1 = multiprocessing.Proess(target=test1)
    p2 = multiprocessing.Proess(target=test2)
    
    p1.start()
    p1.join()  # 確保p1在執(zhí)行結(jié)束后再執(zhí)行p2
    time.sleep(1)  # 或者是在p1執(zhí)行后停頓1秒
    p2.start()
    
# 得出結(jié)果是test1中[1,2,3,4], test2中[1,2,3]
# 在進(jìn)程中不共享全局變量

進(jìn)程和線程的區(qū)別

簡(jiǎn)單的對(duì)比

進(jìn)程:能夠完成多任務(wù),例如一臺(tái)電腦上可以運(yùn)行多個(gè)QQ

(進(jìn)程是系統(tǒng)進(jìn)行資源的分配和調(diào)度的一個(gè)獨(dú)立單位)

線程:能夠完成多任務(wù),例如在同一個(gè)QQ可以開(kāi)多個(gè)聊天窗口

(線程屬于進(jìn)程,是進(jìn)程的一個(gè)實(shí)體,是cpu調(diào)度和分配的基本單位,能更小的獨(dú)立運(yùn)行的基本單位露懒,線程自己使用系統(tǒng)資源)

區(qū)別

1 一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線程

2 線程的劃分尺度小于進(jìn)程(就是占用資源比進(jìn)程少)

3 進(jìn)程在執(zhí)行過(guò)程中擁有獨(dú)立的內(nèi)存單元闯冷,而多個(gè)線程共享內(nèi)存,提高工作效率

4 線程不能獨(dú)立的運(yùn)行,必須依存在進(jìn)程中

5 進(jìn)程就好比工廠的流水線,線程就好比流水線的員工

進(jìn)程之間的通信-Queue隊(duì)列

實(shí)例(僅限一臺(tái)電腦或是服務(wù)器中的兩個(gè)進(jìn)程之間的數(shù)據(jù)共享)

import multiprocessing
# 一個(gè)進(jìn)程向Queue中寫入數(shù)據(jù),另一個(gè)進(jìn)程從Queue獲取數(shù)據(jù)
# 通過(guò)Queue完成了多歌需要配合進(jìn)程間的數(shù)據(jù)共享

def down(q):
    # 下載數(shù)據(jù)
    # 模擬在網(wǎng)上下載數(shù)據(jù)懈词,就簡(jiǎn)單的創(chuàng)建下載好的列表
    data = [1,2,3,4]
    
    # 向隊(duì)列寫入數(shù)據(jù)
    for temp in data:
        q.put(temp)
    print("--數(shù)據(jù)已經(jīng)存到隊(duì)列中---")
    
def fenxi(q):
    # 數(shù)據(jù)處理
    fenxi_data = list()  #或者是fenxi_list = []
    
    # 向保存好的隊(duì)列中獲取數(shù)據(jù)
    while True:
        new_data = q.get()  # new_data是獲取的數(shù)據(jù)
        fenxi_data.append(new_data)
        
        # 判斷:如果隊(duì)被取空的話,就退出
        if q.empty():
            break

if __name__ == "__main__":
    # 創(chuàng)建一個(gè)隊(duì)列
    q = multiprocessing.Queue()
    
    # 創(chuàng)建進(jìn)程  # 傳入實(shí)參隊(duì)列在創(chuàng)建的子進(jìn)程中調(diào)用q
    p1 = multiprocessing.Process(target=down, args=(q,))
    p2 = muultiprocessing.Proess(target=fenxi, args=(q,))
    
    p1.start()
    # p1.join()
    p2.start()

# 以上操作有問(wèn)題,創(chuàng)建的子進(jìn)程p1和p2蛇耀,不能確定那個(gè)子進(jìn)程先運(yùn)行,會(huì)導(dǎo)致p1還沒(méi)有下載好坎弯,p2就直接獲取數(shù)據(jù)纺涤,所以在p1.start()后添加一個(gè)p1.join(), p1.join()的功能就是讓p1執(zhí)行完之后再執(zhí)行其他的進(jìn)程

補(bǔ)充說(shuō)明

初始化Queue()對(duì)象時(shí)(例如q=Queue()),有下列方法

q.put() # 向隊(duì)列導(dǎo)入寫入數(shù)據(jù)

q.get() # 向隊(duì)列下載獲取數(shù)據(jù)

q.empty() # 如果隊(duì)列是空的,返回True, 反之False

q.full() # 如果列隊(duì)滿了,返回True,反之False

進(jìn)程池

進(jìn)程之間的通信

進(jìn)程間通信就是在不同進(jìn)程之間傳播或交換信息抠忘,那么不同進(jìn)程之間存在著什么雙方都可以訪問(wèn)的介質(zhì)呢撩炊?進(jìn)程的用戶空間是互相獨(dú)立的,一般而言是不能互相訪問(wèn)的崎脉,唯一的例外是共享內(nèi)存區(qū)拧咳。但是,系統(tǒng)空間卻是“公共場(chǎng)所”囚灼,所以內(nèi)核顯然可以提供這樣的條件骆膝。除此以外,那就是雙方都可以訪問(wèn)的外設(shè)了灶体。在這個(gè)意義上阅签,兩個(gè)進(jìn)程當(dāng)然也可以通過(guò)磁盤上的普通文件交換信息,或者通過(guò)“注冊(cè)表”或其它數(shù)據(jù)庫(kù)中的某些表項(xiàng)和記錄交換信息赃春。廣義上這也是進(jìn)程間通信的手段愉择,但是一般都不把這算作“進(jìn)程間通信”。因?yàn)槟切┩ㄐ攀侄蔚男侍土耍藗儗?duì)進(jìn)程間通信的要求是要有一定的實(shí)時(shí)性锥涕。

進(jìn)程間通信主要包括管道, 系統(tǒng)IPC(包括消息隊(duì)列,信號(hào)量,共享存儲(chǔ)), SOCKET.

進(jìn)程和線程區(qū)別

定義的區(qū)別:進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立的單位衷戈;線程是進(jìn)程的實(shí)體,是cpu調(diào)度和分配的基本單位

一個(gè)程序至少有一個(gè)進(jìn)程层坠,一個(gè)進(jìn)程至少有一個(gè)線程;

線程的劃分尺度小于進(jìn)程(資源比進(jìn)程少)殖妇,使得多線程程序的并發(fā)性高。

進(jìn)程在執(zhí)行過(guò)程中擁有獨(dú)立的內(nèi)存單元破花,而多個(gè)線程共享內(nèi)存谦趣,從而極大地提高了程序的運(yùn)行效率

線線程不能夠獨(dú)立執(zhí)行,必須依存在進(jìn)程中

可以將進(jìn)程理解為工廠中的一條流水線座每,而其中的線程就是這個(gè)流水線上的工人

優(yōu)缺點(diǎn):線程執(zhí)行開(kāi)銷小前鹅,效率高,,但不利于資源的管理和保護(hù)峭梳;而進(jìn)程正相反舰绘。

協(xié)程

協(xié)程概念

用到更少的資源,:在一個(gè)線程中的某個(gè)函數(shù)葱椭,可以在任何地方保存當(dāng)前函數(shù)的一 些臨時(shí)變量等信息捂寿,然后切換到另外一個(gè)函數(shù)中執(zhí)行,注意不是通過(guò)調(diào)用函 數(shù)的方式做到的孵运,并且切換的次數(shù)以及什么時(shí)候再切換到原來(lái)的函數(shù)都由開(kāi) 發(fā)者自己確定

協(xié)程和線程的區(qū)別

在實(shí)現(xiàn)多任務(wù)時(shí), 線程切換從系統(tǒng)層面遠(yuǎn)不止保存和恢復(fù) CPU上下文這么簡(jiǎn) 單秦陋。 操作系統(tǒng)為了程序運(yùn)行的高效性每個(gè)線程都有自己緩存Cache等等數(shù) 據(jù),操作系統(tǒng)還會(huì)幫你做這些數(shù)據(jù)的恢復(fù)操作治笨。 所以線程的切換非常耗性 能驳概。但是協(xié)程的切換只是單純的操作CPU的上下,所以?秒鐘切換個(gè)上百 萬(wàn)次系統(tǒng)都抗的住旷赖。

如何實(shí)現(xiàn)協(xié)程

1 生成器實(shí)現(xiàn)簡(jiǎn)單的協(xié)程

import time 

def f1():
    while True:
        print("---1----")
        yield
        time.sleep(1)

def f2():
    while True:
        print("---2----")
        yield
        time.sleep(1)
        
if __name__ == "__main__":
    ff1 = f1()
    ff2 = f2()
    while True:
        next(ff1)
        next(ff2)

2 greenlet實(shí)現(xiàn)協(xié)程 (了解)

from greenlet import greenlet
import time

def w1():
    while True:
        print("---1---")
        ww1.switch()  # 使用greenlet模塊中swtich()方法
        time.sleep(1)
        
def w2():
    while True:
        print("---1---")
        ww2.switch()  # 使用greenlet模塊中swtich()方法
        time.sleep(1)
        
if __name__ == "__main__":
    ww1 = greenlet(w1)
    ww2 = greenlet(w2)
    ww1.switch()

3 gevent實(shí)現(xiàn)協(xié)程(重要)

import gevent

def f(n):
    for i in range(n):
        print(gevent.getcurrent(), i)

g1 = gevent.spawn(f,5)
g2 = gevent.spawn(f,5)
g3 = gevent.spawn(f,5)

g1.join()
g2.join()
g3.join()

# 執(zhí)行結(jié)果
<Greenlet "Greenlet-0" at 0x7f9e6251a748: f(5)> 0
<Greenlet "Greenlet-0" at 0x7f9e6251a748: f(5)> 1
<Greenlet "Greenlet-0" at 0x7f9e6251a748: f(5)> 2
<Greenlet "Greenlet-0" at 0x7f9e6251a748: f(5)> 3
<Greenlet "Greenlet-0" at 0x7f9e6251a748: f(5)> 4
<Greenlet "Greenlet-1" at 0x7f9e6251a948: f(5)> 0
<Greenlet "Greenlet-1" at 0x7f9e6251a948: f(5)> 1
<Greenlet "Greenlet-1" at 0x7f9e6251a948: f(5)> 2
<Greenlet "Greenlet-1" at 0x7f9e6251a948: f(5)> 3
<Greenlet "Greenlet-1" at 0x7f9e6251a948: f(5)> 4
<Greenlet "Greenlet-2" at 0x7f9e6251aa48: f(5)> 0
<Greenlet "Greenlet-2" at 0x7f9e6251aa48: f(5)> 1
<Greenlet "Greenlet-2" at 0x7f9e6251aa48: f(5)> 2
<Greenlet "Greenlet-2" at 0x7f9e6251aa48: f(5)> 3
<Greenlet "Greenlet-2" at 0x7f9e6251aa48: f(5)> 4



# 達(dá)成任務(wù)切換
import gevent

def f(n):
    for i in range(n):
        print(gevent.getcurrent(), i)
        # 用來(lái)模擬一個(gè)耗時(shí)操作抡句,不是用time模塊
        gevent.sleep(1)

g1 = gevent.spawn(f,5)
g2 = gevent.spawn(f,5)
g3 = gevent.spawn(f,5)

g1.join()
g2.join()
g3.join()

# 執(zhí)行結(jié)果
<Greenlet "Greenlet-0" at 0x7fc93b84d748: f(5)> 0
<Greenlet "Greenlet-1" at 0x7fc93b84d948: f(5)> 0
<Greenlet "Greenlet-2" at 0x7fc93b84da48: f(5)> 0
<Greenlet "Greenlet-0" at 0x7fc93b84d748: f(5)> 1
<Greenlet "Greenlet-1" at 0x7fc93b84d948: f(5)> 1
<Greenlet "Greenlet-2" at 0x7fc93b84da48: f(5)> 1
<Greenlet "Greenlet-0" at 0x7fc93b84d748: f(5)> 2
<Greenlet "Greenlet-1" at 0x7fc93b84d948: f(5)> 2
<Greenlet "Greenlet-2" at 0x7fc93b84da48: f(5)> 2
<Greenlet "Greenlet-0" at 0x7fc93b84d748: f(5)> 3
<Greenlet "Greenlet-1" at 0x7fc93b84d948: f(5)> 3
<Greenlet "Greenlet-2" at 0x7fc93b84da48: f(5)> 3
<Greenlet "Greenlet-0" at 0x7fc93b84d748: f(5)> 4
<Greenlet "Greenlet-1" at 0x7fc93b84d948: f(5)> 4
<Greenlet "Greenlet-2" at 0x7fc93b84da48: f(5)> 4

進(jìn)程,線程和協(xié)程的對(duì)比(面試重點(diǎn))

A 進(jìn)程是資源分配的單位

B 線程是操作系統(tǒng)調(diào)度的單位

C 進(jìn)程切換需要的資源最大杠愧,效率低

D 線程切換需要的資源一般,效率也很一般

E 協(xié)程切換任務(wù)資源小逞壁,效率高

F 多進(jìn)程流济,多線程根據(jù)cpu的核數(shù)不一樣可能并行,但是協(xié)程是在一個(gè)線程中腌闯,所以是并發(fā)的

G 進(jìn)程不共享資源绳瘟,線程共享資源

GIL(全局解釋器鎖)(面試重點(diǎn))

每個(gè)線程在執(zhí)行過(guò)程中都需要先獲取GIL,保證同一時(shí)刻只有一個(gè)線程可以執(zhí)行代碼姿骏,所以線程是并發(fā)的糖声,都是講并發(fā)運(yùn)行成串行,由此來(lái)控制同一時(shí)間內(nèi)共享數(shù)據(jù)只能被一個(gè)任務(wù)修改,進(jìn)而保證數(shù)據(jù)的安全!

底層知識(shí)

因?yàn)閜ython的線程是調(diào)用操作系統(tǒng)的原生線程蘸泻,這個(gè)原生線程就是C語(yǔ)言寫的原生線程琉苇。因?yàn)閜ython是用C寫的,啟動(dòng)的時(shí)候就是調(diào)用的C語(yǔ)言的接口悦施。因?yàn)閱?dòng)的C語(yǔ)言的遠(yuǎn)程線程并扇,那它要調(diào)這個(gè)線程去執(zhí)行任務(wù)就必須知道上下文,所以python要去調(diào)C語(yǔ)言的接口的線程抡诞,必須要把這個(gè)上限問(wèn)關(guān)系傳給python穷蛹,那就變成了一個(gè)在加減的時(shí)候要讓程序串行才能一次計(jì)算。就是先讓線程1昼汗,再讓線程2.......

多線程用于IO密集型肴熏,如socket,爬蟲(chóng)顷窒,web

多進(jìn)程用于計(jì)算密集型蛙吏,如金融分析

互斥鎖(面試重點(diǎn))

當(dāng)多個(gè)線程幾乎同時(shí)修改一個(gè)共享數(shù)據(jù)的時(shí)候,需要進(jìn)行同步控制蹋肮,線程同步能夠保證多個(gè)線程安全的競(jìng)爭(zhēng)資源出刷,最簡(jiǎn)單的同步機(jī)制就是引入互斥鎖

如何運(yùn)行:某個(gè)線程需要更改共享數(shù)據(jù)的時(shí)候,先鎖定坯辩,此時(shí)資源狀態(tài)為鎖定狀態(tài)馁龟,其他線程不能更改,直到該線程釋放資源漆魔,將資源的狀態(tài)變成非鎖定狀態(tài)坷檩,其他線程才能再次鎖定該資源,互斥鎖保證每次只有一個(gè)線程進(jìn)行操作改抡,從而保證多線程情況的數(shù)據(jù)正確性!

優(yōu)點(diǎn):確保某段關(guān)鍵代碼只能有一個(gè)線程從頭到尾完整的執(zhí)行

缺點(diǎn):A--阻止了多線程的并發(fā)矢炼,包含鎖的某段代碼只能以單線程的模式執(zhí)行,效率大打折扣阿纤。B--由于可以存在多個(gè)鎖句灌,不同的線程持有不同的鎖,并試圖獲取對(duì)方的鎖欠拾,可能會(huì)造成死鎖胰锌!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市藐窄,隨后出現(xiàn)的幾起案子资昧,更是在濱河造成了極大的恐慌,老刑警劉巖荆忍,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件格带,死亡現(xiàn)場(chǎng)離奇詭異撤缴,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)叽唱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門屈呕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人尔觉,你說(shuō)我怎么就攤上這事凉袱。” “怎么了侦铜?”我有些...
    開(kāi)封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵专甩,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我钉稍,道長(zhǎng)涤躲,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任贡未,我火速辦了婚禮种樱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘俊卤。我一直安慰自己嫩挤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布消恍。 她就那樣靜靜地躺著岂昭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪狠怨。 梳的紋絲不亂的頭發(fā)上约啊,一...
    開(kāi)封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音佣赖,去河邊找鬼恰矩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛憎蛤,可吹牛的內(nèi)容都是我干的外傅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼俩檬,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼栏豺!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起豆胸,我...
    開(kāi)封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎巷疼,沒(méi)想到半個(gè)月后晚胡,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體灵奖,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年估盘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瓷患。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡遣妥,死狀恐怖擅编,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情箫踩,我是刑警寧澤爱态,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站境钟,受9級(jí)特大地震影響锦担,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜慨削,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一洞渔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缚态,春花似錦磁椒、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至姨俩,卻和暖如春蘸拔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背环葵。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工调窍, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人张遭。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓邓萨,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親菊卷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子缔恳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • python之進(jìn)程歉甚、線程與協(xié)程 有這么個(gè)例子說(shuō)他們的區(qū)別,幫助理解很有用扑眉。 有一個(gè)老板想開(kāi)一個(gè)工廠生產(chǎn)手機(jī)纸泄。 他需...
    道無(wú)虛閱讀 3,187評(píng)論 0 3
  • 1. 基礎(chǔ)知識(shí) 1.1赖钞、 基本概念、 功能 馮諾伊曼體系結(jié)構(gòu)1聘裁、計(jì)算機(jī)處理的數(shù)據(jù)和指令一律用二進(jìn)制數(shù)表示2雪营、順序執(zhí)...
    yunpiao閱讀 5,309評(píng)論 1 22
  • 必備的理論基礎(chǔ) 1.操作系統(tǒng)作用: 隱藏丑陋復(fù)雜的硬件接口,提供良好的抽象接口衡便。 管理調(diào)度進(jìn)程献起,并將多個(gè)進(jìn)程對(duì)硬件...
    drfung閱讀 3,541評(píng)論 0 5
  • 又來(lái)到了一個(gè)老生常談的問(wèn)題,應(yīng)用層軟件開(kāi)發(fā)的程序員要不要了解和深入學(xué)習(xí)操作系統(tǒng)呢镣陕? 今天就這個(gè)問(wèn)題開(kāi)始谴餐,來(lái)談?wù)劜?..
    tangsl閱讀 4,127評(píng)論 0 23
  • 使用pl/sql創(chuàng)建存儲(chǔ)過(guò)程,具體創(chuàng)建代碼已經(jīng)寫過(guò)茁彭,這里不再贅述总寒。 具體創(chuàng)建過(guò)程如下: 找到Procedures,...
    樂(lè)百事52淑熙閱讀 584評(píng)論 0 1