码迷,mamicode.com
首页 > 编程语言 > 详细

多线程

时间:2019-06-04 22:53:19      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:def   信号量   targe   使用   pass   速度   其他   覆盖   range   

线程的特点

线程是程序运行中的最基本单元,在一个进程内有且至少有一个进程。

 进程:内存独立,CPU独立,速率低共享数据难,安全性高

 线程:内存共享,CPU使用独立,是cpu最小的执行单位

线程的创建方法

1.直接实例化Thread类

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

    task()
    #执行顺序不固定 如果开启线程速度足够快  可能子线程先执行
    print("主线程over")
    print("1",current_thread())

2.创建类覆盖Thread中的run方法

class MyThread(Thread):
    def run(self):
        print("子线程run!")
m = MyThread()
m.start()
print("主线over")

使用方法和进程一样,但是开启线程的代码可以放在任何位置,开启进程的方法只能放在__name__==__main__中

在同一进程中线程间数据共享

from threading import Thread

a = 10
def task():
    global a
    print("子 running...")
    a = 20

t1 = Thread(target=task)
t1.start()

t1.join() # 主线程等待子线执行完毕
print(a)

==》
子 running...
20

进程与线程效率

开启一百个进程

def task():
    pass

if __name__ == __main__:
    st_time=time.time()
    for a in range(100):
        
        t=Process(target=task)
        t.start()

    print(time.time()-st_time)

==3.447035074234009  开启一百个进程花费的时间

开启一百个线程

def task():
    pass

if __name__ == __main__:
    st_time = time.time()
    for a in range(100):

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

    print(time.time()-st_time)
    print(over)
==0.014977693557739258

由此可见线程的开销远远小于进程的开销

守护线程

def task():
print(‘1run‘)
time.sleep(3)
print(‘1over‘)

def task1():
print(‘2run‘)
time.sleep(6)
print(‘2over‘)

t=Thread(target=task)
t1=Thread(target=task1)
t.start()
t1.daemon=True
t1.start()
print(‘over‘)
==>
1run
2run
over
1over

主线程代码执行完后不会立即结束,会等待其他非守护进程

死锁

当程序出现了不止一把锁,分别被不同的线程持有, 有一个资源要想使用必须同时具备两把锁这时候程序就会进程无限卡死状态 ,这就称之为死锁

lock1 = Lock()

# 筷子
lock2 = Lock()

def eat1():
    lock1.acquire()
    print("%s抢到了盘子" % current_thread().name)
    time.sleep(0.5)
    lock2.acquire()
    print("%s抢到了筷子" % current_thread().name)

    print("%s开吃了!" % current_thread().name)
    lock2.release()
    print("%s放下筷子" % current_thread().name)

    lock1.release()
    print("%s放下盘子" % current_thread().name)

def eat2():
    lock2.acquire()
    print("%s抢到了筷子" % current_thread().name)
lock1.acquire()
print("%s抢到了盘子" % current_thread().name) print("%s开吃了!" % current_thread().name) lock1.release() print("%s放下盘子" % current_thread().name) lock2.release() print("%s放下筷子" % current_thread().name) t1 = Thread(target=eat1) t2 = Thread(target=eat2) t1.start() t2.start() ==》 Thread-1抢到了盘子 Thread-2抢到了筷子

如上所示,两个锁可以看作两个许可,线程需要同时拿到两把锁才可以正常运行,当两个线程各拿到一把锁的时候双方都无法正常进行下去,这就出现了死锁

如何避免死锁问题  
        锁不要有多个,一个足够
        如果真的发生了死锁问题,必须迫使一方先交出锁

Rlock

称之为递归锁或者可重入锁,Rlock不使用用来解决死锁问题的

与Lock唯一的区别:
    Rlock同一线程可以多次执行acquire 但是执行几次acquire就应该对应release几次
    如果一个线程已经执行过acquire 其他线程将无法执行acquire

信号量

可以现在被锁定的代码 同时可以被多少线程并发访问

用途: 仅用于控制并发访问   并不能防止并发修改造成的问题

from threading import Semaphore, Thread
import time

s = Semaphore(5)
def task():
    s.acquire()
    print("子run")
    time.sleep(3)
    print("子over")
    s.release()

for i in range(10):
    t = Thread(target=task)
    t.start()

 

多线程

标签:def   信号量   targe   使用   pass   速度   其他   覆盖   range   

原文地址:https://www.cnblogs.com/duGD/p/10976153.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!