zoukankan      html  css  js  c++  java
  • python-day33(线程)

    一. 线程(threading模块)

      线程是CPU的最小执行单位,进程: 资源单位

      multiprocess模块完全模仿了threading模块的接口,二者在使用层面,有很大的相似性

     1 import time
     2 from threading import Thread
     3 #多线程并发,是不是看着和多进程很类似
     4 def func(n):
     5     time.sleep(1)
     6     print(n)
     7 
     8 #并发效果,1秒打印出了所有的数字
     9 for i in range(10):
    10     t = Thread(target=func,args=(i,))
    11     t.start()
    多线程简单实现

      1. 线程的创建

     1 from threading import Thread
     2 import time
     3 def sayhi(name):
     4     time.sleep(2)
     5     print('%s say hello' %name)
     6 
     7 if __name__ == '__main__':
     8     t=Thread(target=sayhi,args=('太白',))
     9     t.start()
    10     print('主线程')
    方式一
     1 import time
     2 from threading import Thread
     3 class Sayhi(Thread):
     4     def __init__(self,name):
     5         super().__init__()
     6         self.name=name
     7     def run(self):
     8         time.sleep(2)
     9         print('%s say hello' % self.name)
    10 
    11 
    12 if __name__ == '__main__':
    13     t = Sayhi('太白')
    14     t.start()
    15     print('主线程')
    方式二

      2. 线程的方法

     1 from threading import Thread
     2 import time
     3 def sayhi(name):
     4     time.sleep(2)
     5     print('%s say hello' %name)
     6 
     7 if __name__ == '__main__':
     8     t=Thread(target=sayhi,args=('太白',))
     9     t2=Thread(target=sayhi,args=('alex',))
    10     t.start()
    11     t2.start()
    12     t.join()  #因为这个线程用了join方法,主线程等待子线程的运行结束
    13 
    14     print('主线程')
    15     print(t.is_alive())  #所以t这个线程肯定是执行结束了,结果为False
    16     print(t2.is_alive()) #有可能是True,有可能是False,看子线程和主线程谁执行的快
    17     '''
    18     egon say hello
    19     主线程
    20     False
    21     '''
    join方法
     1 Thread实例对象的方法
     2   # isAlive(): 返回线程是否活动的。
     3   # getName(): 返回线程名。
     4   # setName(): 设置线程名。
     5 
     6 threading模块提供的一些方法:
     7   # threading.currentThread(): 返回当前的线程变量。
     8   # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
     9   # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果
    10 
    11 
    12 from threading import Thread
    13 import threading
    14 from multiprocessing import Process
    15 import os
    16 
    17 def work():
    18     import time
    19     time.sleep(3)
    20     print(threading.current_thread().getName())
    21 
    22 if __name__ == '__main__':
    23     #在主进程下开启线程
    24     t=Thread(target=work)
    25     t.start()
    26 
    27     print(threading.current_thread())#主线程对象
    28     print(threading.current_thread().getName()) #主线程名称
    29     print(threading.current_thread().ident) #主线程ID
    30     print(threading.get_ident()) #主线程ID
    31     print(threading.enumerate()) #连同主线程在内有两个运行的线程
    32     print(threading.active_count())
    33     print('主线程/主进程')
    34 
    35     '''
    36     打印结果:
    37     <_MainThread(MainThread, started 14104)>
    38     MainThread
    39     14104
    40     14104
    41     [<_MainThread(MainThread, started 14104)>, <Thread(Thread-1, started 17976)>]
    42     2
    43     主线程/主进程
    44     Thread-1
    45     '''
    其他方法

    二. 线程和进程效率对比

     1 from threading import Thread
     2 from multiprocessing import Process
     3 import os
     4 import time
     5 def work():
     6     print('hello')
     7 
     8 if __name__ == '__main__':
     9     s1 = time.time()
    10     #在主进程下开启线程
    11     t=Thread(target=work)
    12     t.start()
    13     t.join()
    14     t1 = time.time() - s1
    15     print('进程的执行时间:',t1)
    16     print('主线程/主进程')
    17     '''
    18     打印结果:
    19     hello
    20     进程的执行时间: 0.0
    21     主线程/主进程
    22     '''
    23 
    24     s2 = time.time()
    25     #在主进程下开启子进程
    26     t=Process(target=work)
    27     t.start()
    28     t.join()
    29     t2 = time.time() - s2
    30     print('线程的执行时间:', t2)
    31     print('主线程/主进程')
    32     '''
    33     打印结果:
    34     hello
    35     线程的执行时间: 0.5216977596282959
    36     主线程/主进程
    37     '''
    效率比较,线程快

    三. 查看子线程和主线程是否在同一进程

    # 查看子线程和主线程是否在同一个进程中
    from threading import Thread
    import os
    def fun():
        print('子线程的pid',os.getpid()) #获得当前 线程pid
    if __name__ == '__main__':
        t = Thread(target=fun,)
        t.start()
        print('主线程的pid',os.getpid()) #获得当前 pid  
    #结果是一样的,是同一进程里

    四. 线程之间的数据是共享的

    from threading import Thread
    def fun():
        global a
        a -= 1
    a = 10
    if __name__ == '__main__':
    
        t = Thread(target=fun,)
        t.start()
        t.join() # 加join 等待t 结束
        print(a) # 9 证明数据是共享的

    五. 验证多线程共享资源造成的数据不安全

    # 验证多线程共享资源造成的数据不安全的问题
    from threading import Thread
    import time
    def fun():
        global a
        t = a
        time.sleep(0.00001)
        t -= 1
        a = t
    a = 20
    if __name__ == '__main__':
        l = []
        for i in range(20):
            t = Thread(target=fun,)
            l.append(t)
            t.start()
        for i in l :
            i.join()
        print(a) # 18 

    六. 加锁解决共享数据不安全的问题

      锁(互斥锁同步锁) #Lock,解决数据共享是数据不安全的问题,

          但同时也牺牲了效率

      

     
     1 from threading import Thread,Lock
     2 import time
     3 def fun(l):
     4     l.acquire()
     5     global a
     6     t = a
     7     time.sleep(0.1)
     8     t -= 1
     9     a = t
    10     l.release()
    11 a = 20
    12 if __name__ == '__main__':
    13     l = []
    14     lock = Lock()
    15     for i in range(20):
    16         t = Thread(target=fun ,args=(lock,))
    17         l.append(t)
    18         t.start()
    19     for i in l:
    20         i.join()
    21     print(a)
    # 加锁解决共享数据不安全的问题

    七. 死锁现象

      死锁现象: 双方互相等待对方释放对方手里拿到的那个锁

      

     1 from threading import Thread ,Lock
     2 import time
     3 
     4 def fun1(lock_A,lock_B):
     5     lock_A.acquire()
     6     time.sleep(1)
     7 
     8     print('A抢到了锁a')
     9     lock_B.acquire()
    10     print('A抢到了锁b')
    11     lock_B.release()
    12     lock_A.release()
    13 def fun2(lock_A,lock_B):
    14     lock_B.acquire()
    15     print('B抢到了b锁')
    16     lock_A.acquire()
    17     print('B抢到了a锁')
    18     lock_A.release()
    19     lock_B.release()
    20 if __name__ == '__main__':
    21     lock_A = Lock()
    22     lock_B = Lock()
    23     t1 = Thread(target=fun1,args=(lock_A,lock_B))
    24     t2 = Thread(target=fun2,args=(lock_A,lock_B))
    25     t1.start()
    26     t2.start()
    死锁现象

    八. 解决死锁, 使用递归锁

      同样是互斥,里面存着个计数器

      进程的死锁和线程的是一样的,而且一般情况下进程之间是数据不共享的,

    不需要加锁,由于线程是对全局的数据共享的,所以对于全局的数据进行操作的时候,要加锁.

    import time
    from threading import Thread,RLock
    fork_lock = noodle_lock = RLock()
    def eat1(name):
        noodle_lock.acquire()
        print('%s 抢到了面条'%name)
        fork_lock.acquire()
        print('%s 抢到了叉子'%name)
        print('%s 吃面'%name)
        fork_lock.release()
        noodle_lock.release()
    
    def eat2(name):
        fork_lock.acquire()
        print('%s 抢到了叉子' % name)
        time.sleep(1) 
        noodle_lock.acquire()
        print('%s 抢到了面条' % name)
        print('%s 吃面' % name)
        noodle_lock.release()
        fork_lock.release()
    
    for name in ['taibai','wulaoban']:
        t1 = Thread(target=eat1,args=(name,))
        t1.start()
    for name in ['alex','peiqi']:
        t2 = Thread(target=eat2,args=(name,))
        t2.start()
    View Code

    九. 守护线程

      守护线程: 主线程等着进程中所有非守护线程的结束,才算结束

      守护进程: 主进程代码结束, 守护进程跟着结束

     1 # 守护线程
     2 from threading import Thread
     3 import time
     4 from multiprocessing import Process
     5 
     6 def fun1():
     7     time.sleep(3)
     8     print(111111111111)
     9 def fun2():
    10     time.sleep(2)
    11     print(222222222222)
    12 if __name__ == '__main__':
    13     # p1 = Process(target=fun1, )
    14     # p2 = Process(target=fun2, )
    15     # p2.daemon = True
    16     # # p1.daemon = True
    17     # p1.start()
    18     # p2.start()
    19 
    20     t1 = Thread(target=fun1,)
    21     t2 = Thread(target=fun2,)
    22     t2.daemon = True
    23     # t1.daemon = True
    24     t1.start()
    25     t2.start()
    26 
    27 
    28     print('结束')
    守护线程和守护进程的区别

    十. 信号量

     1 # 信号量
     2 import time,random
     3 from multiprocessing import Process,Semaphore
     4 from threading import Thread,Semaphore
     5 def fun(i,s):
     6     s.acquire()
     7     time.sleep(random.randint(1,3))
     8     print('%s号来了' %i)
     9     s.release()
    10 
    11 if __name__ == '__main__':
    12     s = Semaphore(4)
    13     for i in range(10):
    14         t = Thread(target=fun,args=(i,s)) # 线程守护
    15         t.start()
    16 
    17     # s = Semaphore(4)    
    18     # for i in range(10):
    19     #     p = Process(target=fun,args=(i,s))   #进程守护
    20     #     p.start()
    守护线程

    十一. 事件

     1 from threading import Thread,Event
     2 e = Event() #默认状态False
     3 print(1)
     4 e.set() #设置状态为True
     5 print(e.is_set()) #查看状态
     6 e.clear() # 设置状态 False
     7 print(e.is_set()) #查看状态
     8 e.set()  #设置状态
     9 print(e.is_set()) #查看状态
    10 e.wait() #判断 等 False  走True
    11 print('结束')
    事件
  • 相关阅读:
    稳扎稳打Silverlight(47) 4.0UI之操作剪切板, 隐式样式, CompositeTransform, 拖放外部文件到程序中
    返璞归真 asp.net mvc (9) asp.net mvc 3.0 新特性之 View(Razor)
    返璞归真 asp.net mvc (6) asp.net mvc 2.0 新特性
    稳扎稳打Silverlight(48) 4.0其它之打印, 动态绑定, 增强的导航系统, 杂七杂八
    精进不休 .NET 4.0 (9) ADO.NET Entity Framework 4.1 之 Code First
    稳扎稳打Silverlight(42) 4.0控件之Viewbox, RichTextBox
    稳扎稳打Silverlight(53) 4.0通信之对WCF NetTcpBinding的支持, 在Socket通信中通过HTTP检索策略文件, HTTP请求中的ClientHttp和BrowserHttp
    稳扎稳打 Silverlight 4.0 系列文章索引
    稳扎稳打Silverlight(54) 4.0通信之对UDP协议的支持: 通过 UdpAnySourceMulticastClient 实现 ASM(Any Source Multicast),即“任意源多播”
    返璞归真 asp.net mvc (8) asp.net mvc 3.0 新特性之 Model
  • 原文地址:https://www.cnblogs.com/Thui/p/10045995.html
Copyright © 2011-2022 走看看