浮躁是人生最大的敌人

并编程复习——线程

Posted on 2019-05-20 21:17  King'home  阅读(107)  评论(0编辑  收藏  举报

进程

线程

1、线程理论

'''
1、什么是线程?
    进程:资源单位
    线程:执行单位
    每个进程中自带一个线程
2、为什么要有线程?
    开一个进程:申请内存空间  耗时
    开线程不要申请空间
    开线程的开销远小于开进程的开销
'''


2、开启线程的方式

# 方式1
from threading import Thread
import time
def task(name)
	print('%s is running'%name)
	time.time(sleep)
	print('%s is over'%name)

if __name__ == '__main__':
    t = Thread(target=task,args =('egon',))
	t.start()
	print('主')
# 方式2
from threading import Thread
import time

class MyThread(Thread)
	def __init__(self,name):
		super().__init__()
        self.name = name
	def run(self)
		print("%s is running"%s)
		time.sleep(3)
		print("%s is over"%s)
if __name__ == '__main__':
	t = Mythread('egon')
	t.start()
	print('主')
    
  • 线程之间数据共享
from threading import Thread

x = 100

def task():
    global x
    x = 666

t = Thread(target=task)
t.start()
t.join()
print(x)


  • 线程互斥锁
from threading import Thread,Lock
import time
import random

mutex = Lock()
n = 100

def task():
    global n
    mutex.acquire()
    tmp = n
    time.sleep(0.1)
    n = tmp -1
    mutex.release()


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
import time


def task(name):
    print('%s is running'%name)
    time.sleep(1)
    print('%s is over'%name)

if __name__ == '__main__':
    t = Thread(target=task,args=('王磊',))
    # t.daemon = True
    t.start()
    print('主')

# 其他方法
from threading import Thread,active_count,current_thread
import os
import time


def task(name):
    # print('%s is running'%name,os.getpid())
    print('%s is running'%name,current_thread().name,current_thread().getName())
    time.sleep(1)
    print('%s is over'%name)

def info(name):
    print('%s is running' % name, current_thread().name, current_thread().getName())
    time.sleep(1)
    print('%s is over' % name)

t = Thread(target=task,args=('关磊',))
t1 = Thread(target=info,args=('关超',))
t.start()
t1.start()
t.join()
print(active_count())  # 当前存活的线程数
print(os.getpid())
print(current_thread().name)
print(current_thread().getName())


3、GIL(全局解释器锁)

  • 什么是GIL(全局解释器锁)

    ​ 保证数据的安全(以牺牲效率来换取数据的安全),阻止同一个进程内的对个进程同时执行(不能并行但是可以是实现并发)

  • GIL存在的原因就是Python线程不是安全的(垃圾回收机制)

问题:python多线程是不是就没有用了呢?
四个任务:计算密集的任务 每个任务耗时10s
单核情况下:
多线程好一点,消耗的资源少一点
多核情况下:
开四个进程:10s多一点
开四个线程:40s多一点

四个任务:IO密集的任务 每个任务io 10s
单核情况下:
多线程好一点
多核情况下:
多线程好一点
多线程和多进程都有自己的优点,要根据项目需求合理选择

  • GIL与普通锁的对比
"""
对于不同的数据,要想保证安全,需要加不同的锁处理
GIL并不能保证数据的安全,它是对Cpython解释器加锁,针对的是线程
保证的是同一个进程下多个线程之间的安全
"""
  • 死锁和递归锁
from threading import Thread,Lock,RLock
import time

"""
自定义锁一次acquire必须对应一次release,不能连续acquire
递归锁可以连续的acquire,每acquire一次计数加一:针对的是第一个抢到我的人
"""
import random
#
# mutexA = Lock()
# mutexB = Lock()
mutexA = mutexB = RLock()  # 抢锁之后会有一个计数 抢一次计数加一 针对的是第一个抢到我的人

class MyThead(Thread):
    def run(self):
        self.func1()
        self.func2()

    def func1(self):
        mutexA.acquire()
        print('%s 抢到A锁了'%self.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(100):
    t = MyThead()
    t.start()

  • 线程queue
import queue

# 1.普通q
# 2.先进后出q
# 3.优先级q

#普通q
# q=queue.Queue(3)
# q.put(1)
# q.put(2)
# q.put(3)
# print(q.get())
# print(q.get())
# print(q.get())

# 先进后出q
# q = queue.LifoQueue(5)
# q.put(1)
# q.put(2)
# q.put(3)
# q.put(4)
# print(q.get())



# 优先级q
# q = queue.PriorityQueue()
# q.put((10,'a'))
# q.put((-1,'b'))
# q.put((100,'c'))
# print(q.get())
# print(q.get())
# print(q.get())


  • 信号量
from threading import Thread,Semaphore
import time
import random
sm = Semaphore(5)  # 五个厕所五把锁
# 跟你普通的互斥锁区别在于,普通的互斥锁是独立卫生间,所有人抢一把锁
# 信号量 公共卫生间 有多个坑,所有人抢多把锁



def task(name):
    sm.acquire()
    print('%s正在蹲坑'%name)
    # 模拟蹲坑耗时
    time.sleep(random.randint(1,5))
    sm.release()


if __name__ == '__main__':
    for i in range(20):
        t = Thread(target=task,args=('伞兵%s号'%i,))
        t.start()



Copyright © 2024 King'home
Powered by .NET 8.0 on Kubernetes