线程 4.线程锁

线程锁

多线程共享资源导致竞争的问题可以使用线程同步来解决
    1.系统调用t1,然后取到num的值,此时为访问上一把锁,即不允许其他线程操作num
    2.t1操作num
    3.t1解锁,其他线程可以继续使用num,且此时num的值为t1操作后的结果
    4.同理在每一个线程访问num时,都要先上锁,访问完成后再解锁,以此保证同一时间只有一个线程在使用资源

发生资源竞争的原因:
    线程的调度是根据系统分配的时间来进行的,此时间可能切断正在进行的修改操作,导致一个修改的中间插入了另一个修改,插入的修改被覆盖
互斥锁根据锁定和解锁的位置,来控制其中的操作完整进行

互斥锁
    当多个线程几乎同时修改某一个共享数据时,需要进行同步控制
    线程同步能够保证多个线程安全访问竞争资源,最简单的实现方法是引入互斥锁
    互斥锁为资源引入一个状态:锁定/非锁定
    某个线程需要修改共享资源时,先将资源的状态设为锁定,其他线程不能修改,直到该线程释放资源,将资源的状态设为非锁定
    互斥锁保证了每次只有一个线程进行写入操作,从而保护多线程情况下数据的正确性
如果在调用obj.acquire()上锁之前,已经被其他线程上了锁,那么此acquire将会阻塞,直到这个锁被解锁

死锁
    在线程间共享多个资源的时候,如果两个线程分别占有一部分资源,且同时等待对方的资源,就会造成死锁
    死锁很少发生,但一旦发生就会导致应用停止响应

import threading
import time

# 互斥锁
num = 0

def work1():
    global num
    lock1.acquire()
    for i in range(100000):
        num += 1
    lock1.release()
    print('work1----------',num)


def work2():
    global num
    for i in range(100000):
        lock1.acquire()
        num += 1
        lock1.release()
    print('work2----------',num)

if __name__ == '__main__':
    # 创建锁
    lock1 = threading.Lock()
    t1 = threading.Thread(target=work1)
    t2 = threading.Thread(target=work2)
    # t1.start()
    # t2.start()
    # while len(threading.enumerate()) != 1:
    #     time.sleep(1)
    # print('main----------',num)

# 死锁
# 如果在return之前不释放锁,return后锁定状态就会保持,等待解锁的线程会一直阻塞
def get_value(index):
    l = [1,3,5,7,9]
    lock1.acquire()
    # 判断索引是否合法
    if index >= len(l):
        print('索引超出列表范围:',index)
        lock1.release()
        return
    print(l[index])
    lock1.release()

if __name__ == '__main__':
    lock1 = threading.Lock()
    for i in range(10):
        t1 = threading.Thread(target=get_value,args=(i,))
        t1.start()


work1---------- 100000
work2---------- 200000
main---------- 200000
1
3
5
7
9
索引超出列表范围: 5
索引超出列表范围: 6
索引超出列表范围: 7
索引超出列表范围: 8
索引超出列表范围: 9
posted @ 2021-12-15 02:42  HyeJeong  阅读(85)  评论(0)    收藏  举报