Python 之并发编程之线程中

.线程锁lock(线程的数据安全)

在数据量较大的时候,线程中的数据会被并发,所有数据会不同步,以至于数据会异常。

下面还介绍了两种的上锁方法。

例:

from threading import Thread, Lock

import time

 

n = 0

 

 

def func1(lock):

    global n

    # time.sleep(0.3)

# print(11)

    for i in range(10000):

        # 正常上锁

        lock.acquire()

        print(n)

        n -= 1

        lock.release()

 

 

def func2(lock):

    global n

    # time.sleep(0.3)

    # print(22)

    for i in range(10000):

        # with 自动上锁解锁

        with lock:

            print(n)

            n += 1

 

 

if __name__ == "__main__":

    # 创建一个锁

    lock = Lock()

    lst = []

    for i in range(10):

        t1 = Thread(target=func1, args=(lock,))

        t2 = Thread(target=func2, args=(lock,))

        t1.start()

        t2.start()

 

        lst.append(t1)

        lst.append(t2)

 

    for i in lst:

        i.join()

 

    print("主线程执行语句结束")

    print(n) # n最后得0,如果没有加上锁的话,不会是0

# 程序执行结束

 

.线程的信号量

例:效果是5个一打印,5个一打印

 

from threading import Semaphore, Thread

import time, random

 

 

def func(i, sem):

    # with简写

    with sem:

        print(i)

        time.sleep(random.uniform(0.1, 1))

 

    """

    # 正常写法

    sem.acquire()

    print(i)

    time.sleep(random.uniform(0.1,1))

    sem.release()

    

    """

 

 

if __name__ == "__main__":

    sem = Semaphore(5)  # 设置几个线程同时运行几个

    for i in range(50):

        Thread(target=func, args=(i, sem)).start()

 

.线程的锁

1.死锁

:只有拿到筷子和面才能吃

noodle_lock = Lock()

chopsticks_lock = Lock()

def eat1(name):

    noodle_lock.acquire()

    print("%s拿到面条" % (name))

    chopsticks_lock.acquire()

    print("%s拿到筷子" % (name))

 

    print("开始吃")

    time.sleep(0.7)

 

    chopsticks_lock.release()

    print("%s放下筷子" % (name))

    noodle_lock.release()

    print("%s放下面条" % (name))

 

 

def eat2(name):

    chopsticks_lock.acquire()

    print("%s拿到筷子" % (name))

    noodle_lock.acquire()

    print("%s拿到面条" % (name))

 

    print("开始吃")

    time.sleep(0.6)

 

    noodle_lock.release()

    print("%s放下面条" % (name))

    chopsticks_lock.release()

    print("%s放下筷子" % (name))

 

 

if __name__ == "__main__":

    name_list1 = ["one", "two"]

    name_list2 = ["three", "four"]

    for name in name_list1:

        Thread(target=eat1, args=(name,)).start()

 

    for name in name_list2:

        Thread(target=eat2, args=(name,)).start()

# 双方都在等待,造成死锁的现象.

2.递归锁RLock

递归锁专门用来解决死锁现象

临时用于快速解决服务器崩溃的异常现象,用递归锁应急

解决应急问题的

(1)基本用法

from threading import Thread,RLock

 

# 递归锁如果3,就对于释放3分锁,忽略上锁过程,进行解锁

rlock = RLock()

def func(name):

    rlock.acquire()

    print(name,1)

    rlock.acquire()

    print(name,2)

    rlock.acquire()

    print(name,3)

 

    rlock.release()

    rlock.release()

    rlock.release()

 

lst = []

for i in range(10):

    t1 = Thread(target=func,args=("name%s" % (i), ))

    t1.start()

    lst.append(t1)

 

for i in lst:

    i.join()

 

print("程序结束了")

 

(2)用递归锁应急解决死锁现象

# 用递归锁应急解决死锁现象

 

noodle_lock = chopsticks_lock = RLock()

def eat1(name):

    noodle_lock.acquire()

    print("%s拿到面条" % (name))

    chopsticks_lock.acquire()

    print("%s拿到筷子" % (name))

 

    print("开始吃")

    time.sleep(0.7)

 

    chopsticks_lock.release()

    print("%s放下筷子" % (name))

    noodle_lock.release()

    print("%s放下面条" % (name))

 

 

def eat2(name):

    chopsticks_lock.acquire()

    print("%s拿到筷子" % (name))

    noodle_lock.acquire()

    print("%s拿到面条" % (name))

 

    print("开始吃")

    time.sleep(0.6)

 

    noodle_lock.release()

    print("%s放下面条" % (name))

    chopsticks_lock.release()

    print("%s放下筷子" % (name))

 

 

if __name__ == "__main__":

    name_list1 = ["one", "two"]

    name_list2 = ["three", "four"]

    for name in name_list1:

        Thread(target=eat1, args=(name,)).start()

 

    for name in name_list2:

        Thread(target=eat2, args=(name,)).start()

3.互斥锁

    从语法上来看,锁是可以互相嵌套的,但是不要使用

    上一次锁,就对应解开一把锁,形成互斥锁

    吃面条和拿筷子是同时的,上一次锁就够了,不要分别上锁

    尽量不要形成锁的嵌套,容易死锁

例:   

from threading import Thread,RLock

mylock = Lock()

def eat1(name):

    mylock.acquire()

    print("%s拿到面条" % (name))

    print("%s拿到筷子" % (name))

 

    print("开始吃")

    time.sleep(0.7)

 

    print("%s放下筷子" % (name))

    print("%s放下面条" % (name))

    mylock.release()

 

 

def eat2(name):

    mylock.acquire()

    print("%s拿到筷子" % (name))

    print("%s拿到面条" % (name))

 

    print("开始吃")

    time.sleep(0.6)

 

    print("%s放下面条" % (name))

    print("%s放下筷子" % (name))

    mylock.release()

 

 

if __name__ == "__main__":

    name_list1 = ["one", "two"]

    name_list2 = ["three", "four"]

    for name in name_list1:

        Thread(target=eat1, args=(name,)).start()

 

    for name in name_list2:

        Thread(target=eat2, args=(name,)).start()

posted @ 2019-04-21 20:45  pycoder_hsz  阅读(145)  评论(0编辑  收藏  举报