文档章节

浅谈线程锁和进程锁

o
 osc_isezqdgg
发布于 2019/09/18 16:08
字数 794
阅读 12
收藏 0

精选30+云产品,助力企业轻松上云!>>>

​ 在python的多线程和多进程中,当我们需要对多线程或多进程的共享资源或对象进行修改操作时,往往会出现因cpu随机调度而导致结果和我们预期不一致的问题,

线程举例:

from threading import Thread,Lock

x = 0
def task():
    global x
    for i in range(200000):
        x = x+1
'''
假设
t1 的 x刚拿到0 保存状态 就被切了
t2 的 x拿到0 进行+1       1
t1 又获得运行了  x = 0  +1  1
思考:一共加了几次1? 加了两次1 真实运算出来的数字本来应该+2 实际只+1
这就产生了数据安全问题.
'''        


if __name__ == '__main__':
    t1 = Thread(target=task)
    t2 = Thread(target=task)
    t3 = Thread(target=task)
    t1.start()
    t2.start()
    t3.start()
    t1.join()
    t2.join()
    t3.join()
    print(x)

479261

from  multiprocessing import Process,Lock
import json,time,os

def search():
    time.sleep(1) # 模拟网络io
    with open('db.txt',mode='rt',encoding='utf-8') as f:
        res = json.load(f)
        print(f'还剩{res["count"]}')

def get():
    with open('db.txt',mode='rt',encoding='utf-8') as f:
        res = json.load(f)
    time.sleep(1) # 模拟网络io
    if res['count'] > 0:
        res['count'] -= 1
        with open('db.txt',mode='wt',encoding='utf-8') as f:
            json.dump(res,f)
            print(f'进程{os.getpid()} 抢票成功')
        time.sleep(1.5) # 模拟网络io
    else:
        print('票已经售空啦!!!!!!!!!!!')

def task():
    search()
    get()

if __name__ == '__main__':

    for i in range(5):
        p = Process(target=task)
        p.start()

还剩1 还剩1 还剩1 还剩1 还剩1 进程6292 抢票成功 进程10604 抢票成功 进程19280 抢票成功 进程272 抢票成功 进程12272 抢票成功

这时就需要对线程或者进程加锁,以保证一个线程或进程在对共享对象进行修改时,其他的线程或进程无法访问这个对象,直至获取锁的线程的操作执行完毕后释放锁。所以,锁在多线程和多进程中起到一个同步的作用,以保护每个线程和进程必要操作的完整执行。

#线程锁
from threading import Thread,Lock

x = 0
mutex = Lock()
def task():
    global x
    mutex.acquire()
    for i in range(200000):
        x = x+1

    mutex.release()

if __name__ == '__main__':
    t1 = Thread(target=task)
    t2 = Thread(target=task)
    t3 = Thread(target=task)
    t1.start()
    t2.start()
    t3.start()
    t1.join()
    t2.join()
    t3.join()
    print(x)

600000

from  multiprocessing import Process,Lock
import json,time,os

def search():
    time.sleep(1) # 模拟网络io
    with open('db.txt',mode='rt',encoding='utf-8') as f:
        res = json.load(f)
        print(f'还剩{res["count"]}')

def get():
    with open('db.txt',mode='rt',encoding='utf-8') as f:
        res = json.load(f)
        # print(f'还剩{res["count"]}')
    time.sleep(1) # 模拟网络io
    if res['count'] > 0:
        res['count'] -= 1
        with open('db.txt',mode='wt',encoding='utf-8') as f:
            json.dump(res,f)
            print(f'进程{os.getpid()} 抢票成功')
        time.sleep(1.5) # 模拟网络io
    else:
        print('票已经售空啦!!!!!!!!!!!')

def task(lock):
    search()

    # 锁住
    lock.acquire()
    get()
    lock.release()
    # 释放锁头

if __name__ == '__main__':
    lock = Lock() # 写在主进程是为了让子进程拿到同一把锁.
    for i in range(15):
        p = Process(target=task,args=(lock,))
        p.start()
        # p.join()

    #  进程锁 是把锁住的代码变成了串行
    #  join 是把所有的子进程变成了串行


# 为了保证数据的安全,串行牺牲掉效率.

还剩1 还剩1 还剩1 还剩1 还剩1 进程16868 抢票成功 票已经售空啦!!!!!!!!!!! 票已经售空啦!!!!!!!!!!! 票已经售空啦!!!!!!!!!!! 票已经售空啦!!!!!!!!!!!

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
多线程浅谈

什么是线程? 线程是"进程"中某个单一顺序的控制流。也被称为轻量进程(lightweight processes)。 为什么使用线程呢? 顾名思义,轻量级进程。一个线程资源的消耗远远低于一个进程,两者相比...

尧山少侠
2015/12/23
9
0
一步步学习Linux多任务编程

系统调用 01、什么是系统调用? 02、Linux系统调用之I/O操作(文件操作) 03、文件描述符的复制:dup(), dup2() 多进程实现多任务 04、进程的介绍 05、Linux可执行文件结构与进程结构 06、多...

Mike江
06/25
0
0
linux高级编程

系统调用 01、什么是系统调用? 02、Linux系统调用之I/O操作(文件操作) 03、文件描述符的复制:dup(), dup2() 多进程实现多任务 04、进程的介绍 05、Linux可执行文件结构与进程结构 06、多...

osc_iz97ycwh
2018/04/09
2
0
一步步学习Linux多任务编程【转】

(转自:https://blog.csdn.net/tennysonsky/article/details/45847551) 系统调用 多进程实现多任务 进程间通信 多线程实现多任务 多任务的同步与互斥 拓展进阶篇...

huangzj0708
03/31
0
0
浅谈线程

程序: 指令和数据的有序集合 进程: 一段代码的动态执行过程,是资源分配的单位 线程: 是进程里面的一条执行路径,是任务调度和独立运行的单位 你吃饭吃到一半,电话来了,你一直到吃完了以...

Eclipse666
2019/03/17
5
0

没有更多内容

加载失败,请刷新页面

加载更多

vue+element-ui JYAdmin后台管理系统模板-集成方案【项目搭建篇2】

项目搭建时间:2020-06-29 本章节:讲述基于vue/cli, 项目的基础搭建。 本主题讲述了: 1、跨域配置 2、axios请求封装 3、eslint配置 4、环境dev,test,pro(开发,测试,线上), run自动调...

osc_p0v6j6lt
7分钟前
0
0
深入解读Dictionary

Dictionary<TKey,TValue>是日常.net开发中最常用的数据类型之一,基本上遇到键值对类型的数据时第一反应就是使用这种散列表。散列表特别适合快速查找操作,查找的效率是常数阶O(1)。那么为什...

osc_ictoo263
9分钟前
0
0
面试: Vue数组的变异方法

Vue数组的变异方法 Vue 包含一组观察数组的变异方法,所以它们也将会触发视图更新。这些方法如下: push() pop() shift() unshift() splice() sort() reverse() push():往数组最后面添加一个...

osc_ee3ody6v
10分钟前
27
0
@ConfigurationProperties 注解解析

最近项目中实现读写分离时有用到@ConfigurationProperties注解,通过不同的前缀来配置不同的数据源信息 如果没有使用过springboot的可能对这个注解不太熟悉,下面简单的对这个注解做个解析: ...

osc_47qtuhkb
12分钟前
9
0
B站前端的学习视频分享,都是我自己看过,觉得有帮助的

B站前端学习视频分享 都是我自己发时间看过,觉得不错的(*^_^*) 1. es6, promise, async/await, vue的安装, 说得很清楚(高校计算机毕业班的老师上传的网课) https://space.bilibili.com/4...

osc_bgpugm2v
13分钟前
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部