多任务-线程之资源竞争问题(互斥锁)

1.在多线程中,不可避免的一个问题,就是全局变量资源存在着被多个线程调用的问题,在调用的过程中就存在着资源竞争

2.这种资源竞争是如何产生的呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import threading
import time
 
g_num = 0
 
def work1(num):
    global g_num
    for i in range(num):
        g_num += 1
    print("----in work1, g_num is %d---"%g_num)
 
 
def work2(num):
    global g_num
    for i in range(num):
        g_num += 1
    print("----in work2, g_num is %d---"%g_num)
 
 
print("---线程创建之前g_num is %d---"%g_num)
 
t1 = threading.Thread(target=work1, args=(100,))
t1.start()
 
t2 = threading.Thread(target=work2, args=(100,))
t2.start()
 
while len(threading.enumerate()) != 1:
    time.sleep(1)
 
print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)

如同上述代码,当线程执行次数有限时,全局资源不会发生大的变化,但是当高并发时,就会产生资源竞争问题,如以下代码:

复制代码
import threading
import time

g_num = 0

def work1(num):
    global g_num
    for i in range(num):
        g_num += 1
    print("----in work1, g_num is %d---"%g_num)


def work2(num):
    global g_num
    for i in range(num):
        g_num += 1
    print("----in work2, g_num is %d---"%g_num)


print("---线程创建之前g_num is %d---"%g_num)

t1 = threading.Thread(target=work1, args=(1000000,))
t1.start()

t2 = threading.Thread(target=work2, args=(1000000,))
t2.start()

while len(threading.enumerate()) != 1:
    time.sleep(1)

print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)
复制代码

3.如何解决资源竞争问题?

当存在多个线程或者进程同时调用一个全局变量资源,并且会对它进行修改时,可以采用上锁这个方法,来解决资源竞争问题。

首先,需要了解什么叫做资源竞争?

资源竞争是指,一个全局变量资源在多个线程或者进程中被同时调用,造成该全局变量资源不断的被修改。

解决方法:采用全局变量锁,每当线程调用全局变量时,就将该资源上锁,不允许被调用,只有当调用结束后才打开锁,这里引入互斥锁,能够保证全局变量资源的安全。

互斥锁的两种状态:锁定/非锁定

解决资源竞争的好处:互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

4.互斥锁的定义

当在请求之前,资源没有被上锁,那么请求并不会堵塞;如果在请求之前,是被锁上的, 那么请求就处于一个堵塞状态,只有当前得锁被打开之后,才能在次上锁。

互斥锁的优缺点:

  优点:确保了某段关键代码只能由一个线程从头到尾完整地执行

  缺点:阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了

     由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对方持有的锁时,可能会造成死锁

1
2
3
4
5
6
7
8
# 创建锁
mutex = threading.Lock()
 
# 锁定
mutex.acquire()
 
# 释放
mutex.release()
posted @   zxh_python  阅读(2999)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
点击右上角即可分享
微信分享提示