四.线程锁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()

Python 之并发编程之线程中的更多相关文章

  1. Python并发编程之线程中的信息隔离(五)

    大家好,并发编程 进入第三篇. 上班第一天,大家应该比较忙吧.小明也是呢,所以今天的内容也很少.只要几分钟就能学完. 昨天我们说,线程与线程之间要通过消息通信来控制程序的执行. 讲完了消息通信,今天就 ...

  2. Python 之并发编程之线程下

    七.线程局部变量 多线程之间使用threading.local 对象用来存储数据,而其他线程不可见 实现多线程之间的数据隔离 本质上就是不同的线程使用这个对象时,为其创建一个只属于当前线程的字典 拿空 ...

  3. Python 之并发编程之线程上

    一.线程概念 进程是资源分配的最小单位 线程是计算机中调度的最小单位 多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间,相当于一个车间内有多条流水线,都 ...

  4. python 之 并发编程(线程Event、协程)

    9.14 线程Event connect线程执行到event.wait()时开始等待,直到check线程执行event.set()后立即继续线程connect from threading impor ...

  5. Python 之并发编程之进程中(守护进程(daemon)、锁(Lock)、Semaphore(信号量))

    五:守护进程 正常情况下,主进程默认等待子进程调用结束之后再结束守护进程在主进程所有代码执行完毕之后,自动终止kill -9 进程号 杀死进程.守护进程的语法:进程对象.daemon = True设置 ...

  6. python 之 并发编程(线程理论,开启线程的两种方式,进程与线程的区别,线程对象的其他方法)

    9.9 线程理论 1.什么是线程 线程指的是一条流水线的工作过程 进程根本就不是一个执行单位,进程其实是一个资源单位,一个进程内自带一个线程,线程才是执行单位 2.进程VS线程 同一进程内的线程们共享 ...

  7. 《转载》Python并发编程之线程池/进程池--concurrent.futures模块

    本文转载自Python并发编程之线程池/进程池--concurrent.futures模块 一.关于concurrent.futures模块 Python标准库为我们提供了threading和mult ...

  8. python并发编程之线程/协程

    python并发编程之线程/协程 part 4: 异步阻塞例子与生产者消费者模型 同步阻塞 调用函数必须等待结果\cpu没工作input sleep recv accept connect get 同 ...

  9. Python 3 并发编程多进程之队列(推荐使用)

    Python 3 并发编程多进程之队列(推荐使用) 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的. 可以往 ...

随机推荐

  1. 编译和链接(lib和dll区别)(转载)

    1.头文件并不参加链接和编译.编译器第一步要做的就是简单的把头文件在包含它的源文件中展开.不知你是否能理解这句话.也就是头文件里面有什么内容,通通把它移到包含这个头文件的源文件里.(我觉得这是个很重要 ...

  2. GitHub网页版基本操作

    创建存储库 登录GitHub进入主页,点击头像左边的加号,创建存储库 填写存储库名称.描述,根据需求设置其他选项.点击“Create repository”按钮 创建分支 打开之前创建好的存储库,点击 ...

  3. 对象析构谈—— delete this 的使用及注意事项

    this对象是必须是用 new操作符分配的(而不是用new[],也不是用placement new,也不是局部对象,也不是global对象): delete this后,不能访问该对象任何的成员变量及 ...

  4. js实现汉字转拼音

    汉字转拼音,每个字首字母大写:pinyin.getFullChars(name); 提取首字母并大写:pinyin.getCamelChars(name); /* --- description: P ...

  5. honoka和格点三角形(牛客寒假训练营day1)

    可以把面积为1的好三角形分成两类分开统计:两条边和两个坐标轴平行:只有一条边和某个坐标轴平行. 对于第一种情况,一定是1*2或者2*1的形式,一个1*2的矩形中含有4个不同的三角形.总数是4*((n- ...

  6. 最小树形图模板 UVA11183

    题意:给定n个节点m条边的有向带权图,求以0为根节点的最小树形图权值大小 用这个代码的时候要注意,这里的数据是从0开始的,边也是从0开始算, 所以在打主代码的时候,如果是从1开始,那么算法里面的从0开 ...

  7. 你了解getBoundingClientRect()?

    理解:getBoundingClientRect用于获取某个元素相对于视窗的位置集合.集合中有top, right, bottom, left等属性. 1.语法:这个方法没有参数. rectObjec ...

  8. python中写入txt文件需要换行,以及\r 和\n

    在Python中,用open()函数打开一个txt文件,写入一行数据之后需要一个换行 如果直接用 f.write(’\n’)只会在后面打印一个字符串’\n’,而不是换行’需要用 f.write(’\r ...

  9. web前端技能考核(阿里巴巴)

  10. JAVA 爬虫框架webmagic 初步使用Demo

    一想到做爬虫大家第一个想到的语言一定是python,毕竟python比方便,而且最近也非常的火爆,但是python有一个全局锁的概念新能有瓶颈,所以用java还是比较牛逼的, webmagic 官网 ...