首页 > 编程语言 > 详细

python-线程

时间:2020-03-06 18:58:18      阅读:86      评论:0      收藏:0      [点我收藏+]

线程的概念&与进程的区别?

进程是计算机分配资源的最小单位
线程是计算机中可以被cpu调度的最小单位
一个进程中可以有多个线程,同一个进程中的线程可以共享此进程中的资源,一个进程中至少有一个线程(一个应用程序中至少有一个进程)
?
在python中因为有GIL锁,同一时刻保证一个进程中只有一个线程可以被cpu调度,所以在使用python开发时要注意:
计算密集型,用多进程
   IO密集型,用多线程
默认进程之间不能进行资源共享,如果非要进行通信,可以基于:文件/网络/Queue

多线程的应用

  • 快速应用

    import threading
    def task(arg):
       pass
    t = threading.Thread(target=task,args=(1,)) # 实例化一个线程
    t.start() # 将线程提交给cpu 什么时候被调度看cpu
    import threading
    def task(arg):
    ret = requests.get(arg)
    file_name = arg.rsplit(‘/‘, maxsplit=1)[-1]
    with open(file_name, mode=‘wb‘) as f:
    f.write(ret.content)

    for url in url_list:
    # 实例化一个线程对象
    t = threading.Thread(target=task,args=(url,))
    # 将线程提交给cpu
    t.start()
  • 常见的方法

    • t.start()  将线程提交给cpu,由cpu来进行调度

    • t.join()  等待

    import threading
    ?
    ?
    # 示例1
    """
    loop = 10000000
    number = 0
    ?
    def _add(count):
      global number
      for i in range(count):
          number += 1
    ?
    ?
    t = threading.Thread(target=_add,args=(loop,))
    t.start()
    ?
    t.join()
    print(number)
    """
    ?
    # 示例2
    """
    loop = 10000000
    number = 0
    ?
    def _add(count):
      global number
      for i in range(count):
          number += 1
    ?
    def _sub(count):
      global number
      for i in range(count):
          number -= 1
    ?
    t1 = threading.Thread(target=_add,args=(loop,))
    t2 = threading.Thread(target=_sub,args=(loop,))
    t1.start()
    t2.start()
    ?
    print(number)
    """
    ?
    ?
    # 示例3
    """
    loop = 10000000
    number = 0
    ?
    def _add(count):
      global number
      for i in range(count):
          number += 1
    ?
    def _sub(count):
      global number
      for i in range(count):
          number -= 1
    ?
    t1 = threading.Thread(target=_add,args=(loop,))
    t2 = threading.Thread(target=_sub,args=(loop,))
    t1.start()
    t2.start()
    t1.join() # t1线程执行完毕,才继续往后走
    t2.join() # t2线程执行完毕,才继续往后走
    ?
    print(number)
    """
    ?
    # 示例4
    """
    loop = 10000000
    number = 0
    ?
    def _add(count):
      global number
      for i in range(count):
          number += 1
    ?
    def _sub(count):
      global number
      for i in range(count):
          number -= 1
    ?
    t1 = threading.Thread(target=_add,args=(loop,))
    t2 = threading.Thread(target=_sub,args=(loop,))
    t1.start()
    t1.join() # t1线程执行完毕,才继续往后走
    t2.start()
    t2.join() # t2线程执行完毕,才继续往后走
    ?
    print(number)
    """
  • t.setDaemon()    设置称为守护线程

    import threading
    import time
    def task(arg):
       time.sleep(5)
       print(‘任务‘)
    t = threading.Thread(target=task,args=(11,))
    t.setDaemon(True)
    t.start()
    print(‘END‘)
  • 线程名称的设置和获取

    import threading
    def task(arg):
       # 获取当前执行此代码的线程
       name = threading.current_thread().getName()
       print(name)
    for i in range(10):
       t = threading.Thread(target=task,args=(11,))
       t.setName(‘日魔-%s‘ %i )
       t.start()
  • run()  自定义线程时,cpu调度执行的方法

    class RiMo(threading.Thread):
       def run(self):
           print(‘执行此线程‘,self._args)
    ?
    obj = RiMo(args=(100,))
    obj.start()

练习题:基于socket和多线程实现类似与socketserver模块的功能

import socket
import threading
?
?
def task(connect,address):
   pass
?
?
server = socket.socket()
server.bind((‘127.0.0.1‘,9000))
server.listen(5)
while True:
   conn,addr = server.accept()
   # 处理用户请求
   t = threading.Thread(target=task,args=(conn,addr,))
   t.start()

多线程安全

多个线程同时去操作一个‘东西’,不要存在数据混乱

线程安全:logging模块/列表

线程不安全:自己做文件操作/同时修改一个数字

使用锁来保证数据安全,来了多个线程,使用锁让他们排队,逐一执行

  • Lock

    import threading
    import time
    num = 0
    # 线程锁
    lock = threading.Lock()
    def task():
       global num
       # # 申请锁
       # lock.acquire()
       # num += 1
       # time.sleep(0.2)
       # print(num)
       # # 释放锁
       # lock.release()
       with lock:
           num += 1
           time.sleep(0.2)
           print(num)
    for i in range(10):
       t = threading.Thread(target=task)
       t.start()
  • RLock

    import threading
    import time
    num = 0
    # 线程锁
    lock = threading.RLock()
    def task():
       global num
       # 申请锁
       lock.acquire()
       num += 1
       lock.acquire()
       time.sleep(0.2)
       print(num)
       # 释放锁
       lock.release()
       lock.release()
    for i in range(10):
       t = threading.Thread(target=task)
       t.start()

练习题:基于线程锁完成一个单例模式

import threading
import time
class Singleton:
   instance = None
   lock = threading.RLock()
   def __init__(self, name):
       self.name = name
   def __new__(cls, *args, **kwargs):
       if cls.instance:
           return cls.instance
       with cls.lock:
           if cls.instance:
               return cls.instance
           time.sleep(0.1)
           cls.instance = object.__new__(cls)
       return cls.instance
def task():
   obj = Singleton(‘x‘)
   print(obj)
for i in range(10):
   t = threading.Thread(target=task)
   t.start()
?
# 执行1000行代码
data = Singleton(‘asdfasdf‘)
print(data)

GIL 全局解释器锁

同一时刻保证一个进程中只有一个线程可以被cpu调度,所以在使用Python开发时要注意:
计算密集型,用多进程.
IO密集型,用多线程.

python中如果创建多线程无法应用计算机的多核优势

python-线程

原文:https://www.cnblogs.com/womenzt/p/12427995.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!