总结二十八

Posted tzz1995

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了总结二十八相关的知识,希望对你有一定的参考价值。

GIL全局解释器锁

"""
In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple
native threads from executing Python bytecodes at once. This lock is necessary mainly
because CPython’s memory management is not thread-safe.
"""
"""
ps:python解释器有很多种  最常见的就是Cpython解释器
GIL本质也是一把互斥锁:将并发变成串行牺牲效率保证数据的安全 
用来阻止同一个进程下的多个线程的同时执行(同一个进程内多个线程无法实现并行但是可以实现并发)
    python的多线程没法利用多核优势  是不是就是没有用了?
    
GIL的存在是因为CPython解释器的内存管理不是线程安全的

垃圾回收机制
    1.引用计数
    2.标记清除
    3.分代回收


研究python的多线程是否有用需要分情况讨论
四个任务 计算密集型的  10s
单核情况下
    开线程更省资源
多核情况下
    开进程 10s
    开线程 40s

四个任务 IO密集型的  
单核情况下
    开线程更节省资源
多核情况下
    开线程更节省资源
"""
# 计算密集型
from multiprocessing import Process
from threading import Thread
import os,time
def work():
    res=0
    for i in range(100000000):
        res*=i

if __name__ == __main__:
    l=[]
    print(os.cpu_count())  # 本机为6核
    start=time.time()
    for i in range(6):
        # p=Process(target=work) #耗时  4.732933044433594
        p=Thread(target=work) #耗时 22.83087730407715
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop=time.time()
    print(run time is %s %(stop-start))
# IO密集型
from multiprocessing import Process
from threading import Thread
import threading
import os,time
def work():
    time.sleep(2)

if __name__ == __main__:
    l=[]
    print(os.cpu_count()) #本机为6核
    start=time.time()
    for i in range(4000):
        p=Process(target=work) #耗时9.001083612442017s多,大部分时间耗费在创建进程上
        # p=Thread(target=work) #耗时2.051966667175293s多
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop=time.time()
    print(run time is %s %(stop-start))

"""
python的多线程到底有没有用
需要看情况而定  并且肯定是有用的

多进程+多线程配合使用
"""

 

GIL与普通的互斥锁

from threading import Thread
import time

n = 100

def task():
    global n
    tmp = n
    # time.sleep(1)
    n = tmp -1

t_list = []
for i in range(100):
    t = Thread(target=task)
    t.start()
    t_list.append(t)

for t in t_list:
    t.join()

print(n)

 

死锁

from threading import Thread,Lock,current_thread,RLock
import time
"""
Rlock可以被第一个抢到锁的人连续的acquire和release
每acquire一次锁身上的计数加1
每release一次锁身上的计数减1
只要锁的计数不为0 其他人都不能抢

"""
# mutexA = Lock()
# mutexB = Lock()
mutexA = mutexB = RLock()  # A B现在是同一把锁,解决死锁问题

class MyThread(Thread):
    def run(self):  # 创建线程自动触发run方法 run方法内调用func1 func2相当于也是自动触发
        self.func1()
        self.func2()

    def func1(self):
        mutexA.acquire()
        print(%s抢到了A锁%self.name)  # self.name等价于current_thread().name
        mutexB.acquire()
        print(%s抢到了B锁%self.name)
        mutexB.release()
        print(%s释放了B锁%self.name)
        mutexA.release()
        print(%s释放了A锁%self.name)

    def func2(self):
        mutexB.acquire()
        print(%s抢到了B锁%self.name)
        time.sleep(1)
        mutexA.acquire()
        print(%s抢到了A锁 % self.name)
        mutexA.release()
        print(%s释放了A锁 % self.name)
        mutexB.release()
        print(%s释放了B锁 % self.name)

for i in range(10):
    t = MyThread()
    t.start()

# class Demo(object):
# #     pass
# #
# # obj1 = Demo()
# # obj2 = Demo()
# # print(id(obj1),id(obj2))
"""
只要类加括号实例化对象
无论传入的参数是否一样生成的对象肯定不一样
单例模式除外


自己千万不要轻易的处理锁的问题  

"""

 

信号量

# 信号量可能在不同的领域中 对应不同的知识点
"""
互斥锁:一个厕所(一个坑位)
信号量:公共厕所(多个坑位)
"""
from threading import Semaphore,Thread
import time
import random

sm = Semaphore(5)  # 造了一个含有五个的坑位的公共厕所

def task(name):
    sm.acquire()
    print(%s占了一个坑位%name)
    time.sleep(random.randint(1,3))
    sm.release()

for i in range(40):
    t = Thread(target=task,args=(i,))
    t.start()

 

event事件

from threading import Event,Thread
import time

# 先生成一个event对象
e = Event()

def light():
    print(红灯正亮着)
    time.sleep(3)
    e.set()  # 发信号
    print(绿灯亮了)

def car(name):
    print(%s正在等红灯%name)
    e.wait()  # 等待信号
    print(%s加油门飙车了%name)

t = Thread(target=light)
t.start()

for i in range(10):
    t = Thread(target=car,args=(伞兵%s%i,))
    t.start()

 

线程q

import queue
"""
同一个进程下的多个线程本来就是数据共享 为什么还要用队列

因为队列是管道+锁  使用队列你就不需要自己手动操作锁的问题 

因为锁操作的不好极容易产生死锁现象
"""

q = queue.Queue()
q.put(hahha)
print(q.get())

q = queue.LifoQueue()
q.put(1)
q.put(2)
q.put(3)
print(q.get())

q = queue.PriorityQueue()
# 数字越小 优先级越高
q.put((10,haha))
q.put((100,hehehe))
q.put((0,xxxx))
q.put((-10,yyyy))
print(q.get())

 

以上是关于总结二十八的主要内容,如果未能解决你的问题,请参考以下文章

-考研第二十八周总结-

Linux学习总结(二十八) 数据同步工具 rsync

每日算法&面试题,大厂特训二十八天——第二十八天(数组)

每日算法&面试题,大厂特训二十八天——第二十七天(函数)

每日算法&面试题,大厂特训二十八天——第二十三天(树)

每日算法&面试题,大厂特训二十八天——第二十六天(循环)