内存管理与多线程

内存管理与多线程(python)

内存管理

1、赋值语句内存分析
使用 id() 访问内存地址
在这里插入图片描述
使用 is 比较内存引用地址是否相等

2、垃圾回收机制



class Cat(object):

    def __init__(self):
        print('对象产生了: {0}'.format(id(self)))

    def __del__(self):
        print('对象删除了: {0}'.format(id(self)))


def f0():
    """ 自动回收内存 """
    while True:
        c1 = Cat()


def f1():
    """ 一直在被引用,不会被回收 """
    l = []
    while True:
        c1 = Cat()
        l.append(c1)
        print(len(l))


if __name__ == '__main__':
    f1()

(1)以引用计数为主,分代收集为辅
引用计数:
a、每个对象都有存有指向该对象的引用总数
b、查看某个对象的引用计数sys.getrefcount()
c、可以使用del关键字删除某个引用

import sys

i = 1

l = []
l2 = l
l3 = l

l5 = l3
print(sys.getrefcount(l))
del l2


# 对象l被引用的数量
print(sys.getrefcount(l))

print('xxxxxxxxxxxxx')
print(sys.getrefcount(i))
a = i
print(sys.getrefcount(i))

(2)如果一个对象的引用数为0,python虚拟机就会回收这个对象的内存

垃圾回收:
满足特定条件,自动启动垃圾回收
等python运行时,会记录其中分配对象(object allocation)和取消分配对象(object deallocation)的次数
当两者的差值高于某个阈值时,垃圾回收才会启动
查看阙值gc.get_threshold()

分代回收:
python将所有的对象分为0, 1, 2三代
所有的新建对象都是0代对象
当某一代对象经历过垃圾回收,依然存活,那么它就被归入下一代对象

手动回收:
gc.collect()手动回收
objgraph模块中的count()记录当前类产生的实例对象的个数

import gc, sys
import objgraph


print(gc.get_threshold())


class Persion(object):
    pass


class Cat(object):
    pass


p = Persion()
c = Cat()
p.name = 'Susan'
p.pet = c

c.master = p
print(sys.getrefcount(p))
print(sys.getrefcount(c))

# del p
# del c

# 手动执行垃圾回收
gc.collect()
print(objgraph.count('Persion'))
print(objgraph.count('Cat'))

(3)引用计数的缺陷是循环引用的问题

3、内存管理机制
内存池(memory pool)机制:预先在内存中申请一定数量的,大小相等的内存块留作备用,当有新的内存需求时,就先从内存池中分配内存给这个需求,不够了之后在申请新的内存

python多线程

1、对多核的利用
GIL——全局解释器锁
GIL只是强制在任何时候只有一个线程可以执行python代码
I/O密集型应用与CPU密集型应用

GIL执行顺序:
设置GIL;
切换进一个线程去运行;
执行下面操作之一:指定数量的字节码指令;线程主动让出控制权(可以调用time.sleep(0)来完成)
把线程设置回睡眠状态(切换出线程)
解锁GIL
重复上述步骤

2、线程
在同一个进程下执行,并共享相同的上下文
一个进程中的各个线程与主线程共享同一片数据空间
线程包括开始、执行顺序和结束三部分
它可以被强占和临时挂起
一般以并发方式进行

(1)实现一个线程
用threading模块代替thread模块
用threading.Tread创建线程
start()启动线程
join()挂起线程
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

import threading
import time


def loop():
    """ 新的线程执行的代码 """
    n = 0
    while n < 5:
        print(n)
        now_thread = threading.current_thread()
        print('[loop]now  thread name : {0}'.format(now_thread.name))
        time.sleep(1)
        n += 1


def use_thread():
    """ 使用线程来实现 """
    # 当前正在执行的线程名称
    now_thread = threading.current_thread()
    print('now  thread name : {0}'.format(now_thread.name))
    # 设置线程
    t = threading.Thread(target=loop, name='loop_thread')
    # 启动线程
    t.start()
    # 挂起线程
    t.join()


if __name__ == '__main__':
    use_thread()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值