Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >python的进程与线程

python的进程与线程

作者头像
步履不停凡
发布于 2019-08-23 09:42:56
发布于 2019-08-23 09:42:56
73900
代码可运行
举报
文章被收录于专栏:逸繁逸繁
运行总次数:0
代码可运行

进程、线程的含义?

1.什么是进程?

  进程是指运行中的应用程序,每个进程都有自己独立的地址空间(内存空间)。比如用户点击桌面的IE浏览器,就启动了一个进程,操作系统就会为该进程分配独立的地址空间。当用户再次点击IE浏览器,又启动了一个进程,操作系统将为新的进程分配新的独立的地址空间。多进程就是“多任务”,就像使用电脑时同时打开浏览器上网、打开播放器听歌、后台还默默运行着杀毒软件一样。现代操作系统如Mac OS X,UNIXLinuxWindows等都支持多进程,每启动一个进程,操作系统便为该进程分配一个独立的内存空间。

2.什么是线程?

  线程是进程中的一个实体,是被系统独立调度和分派的基本单位。一个进程可以有一个线程,也可以有多个线程。   线程自己不拥有独立的系统资源,只拥有一点在运行中必不可少的资源,它可与同属一个进程的其它线程共享当前进程所拥有的全部资源。   一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。   线程有就绪(runnable)、阻塞(blocked)和运行(running)三种基本状态以及新建(new)和死亡(dead)状态。

为什么要有多进程和多线程?

  每个进程至少要干一件事,比如一个编辑器既要打字输入同时又要检测打错的拼写有时候还要区分一些关键字高亮显示,它们同属于编辑器这个进程,我们把编辑器作为一个进程,而以上这些工作就是它的子任务,如何实现他们同时工作呢?就是让每个子任务即线程短暂运行交替执行,由于它们彼此之间交替太快了,看起来就像同时运行一样。(真正的多线程需要多核CPU才能实现) 当我们要让一个python程序执行多个任务时,我们可以用多个进程或多个线程来完成我们的任务,他们之间彼此同时交替进行甚至一个任务依赖于另一个任务执行的结果,他们需要相互通信和协调,所以我们就需要用到多进程和多线程编程了。

实现多进程和多线程

1.多进程

  linux下可使用os模块的fork()。   Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import os

print('Process (%s) start...' % os.getpid())
# Only works on Unix/Linux/Mac:
pid = os.fork()
if pid == 0:
  print('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid()))
else:
  print('I (%s) just created a child process (%s).' % (os.getpid(), pid))

  windows下可以使用multiprocessing模块   multiprocessing模块提供了一个Process类来代表一个进程对象,下面的例子演示了启动一个子进程并等待其结束:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from multiprocessing import Process
import os

# 子进程要执行的代码
def run_proc(name):
  print('Run child process %s (%s)...' % (name, os.getpid()))

if __name__=='__main__':
  print('Parent process %s.' % os.getpid())
  p = Process(target=run_proc, args=('test',))
  print('Child process will start.')
  p.start()
  p.join()
  print('Child process end.')

  创建子进程时,只需要传入一个执行函数和函数的参数,创建一个Process实例,用start()方法启动。   join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步。

  Pool   如果要启动大量的子进程,可以用进程池的方式批量创建子进程:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from multiprocessing import Pool
import os, time, random

def long_time_task(name):
  print('Run task %s (%s)...' % (name, os.getpid()))
  start = time.time()
  time.sleep(random.random() * 3)
  end = time.time()
  print('Task %s runs %0.2f seconds.' % (name, (end - start)))

if __name__=='__main__':
  print('Parent process %s.' % os.getpid())
  p = Pool(4)
  for i in range(5):
  p.apply_async(long_time_task, args=(i,))
  print('Waiting for all subprocesses done...')
  p.close()
  p.join()
  print('All subprocesses done.')

  对Pool对象调用join()方法会等待所有子进程执行完毕,调用join()之前必须先调用close(),调用close()之后就不能继续添加新的Process了。

  子进程   很多时候,子进程并不是自身,而是一个外部进程。我们创建了子进程后,还需要控制子进程的输入和输出。

  subprocess模块可以让我们非常方便地启动一个子进程,然后控制其输入和输出。

  下面的例子演示了如何在Python代码中运行命令nslookup www.python.org,这和命令行直接运行的效果是一样的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import subprocess

print('$ nslookup www.python.org')
r = subprocess.call(['nslookup', 'www.python.org'])
print('Exit code:', r)

2.多线程

  使用threading模块实现多线程,Python的线程是真正的Posix Thread,而不是模拟出来的线程。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import time, threading

def loop():
  print('线程 %s 在运行' % threading.current_thread().name)
  n = 0
  while n < 5:
    n = n + 1
    print('线程 %s >>> %s' % (threading.current_thread().name, n))
    time.sleep(1)
  print('线程 %s 结束.' % threading.current_thread().name)

print('线程 %s 在运行' % threading.current_thread().name)
t = threading.Thread(target=loop, name='子线程1')
t2 = threading.Thread(target=loop, name='子线程2')
t.start()
t2.start()
t.join()
t2.join()
print('线程 %s 结束.' % threading.current_thread().name)

或者

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import time, threading

num=0
lock = threading.Lock()

def action_one():
  global num
  for i in range(3):
    lock.acquire()
    try:
      print("线程1 %d"%num)
      num+=1
      time.sleep(1)
    finally:
      lock.release()

def action_two():
  global num
  for i in range(3):
    lock.acquire()
    try:
      print("线程2 %d"%num)
      num+=1
      time.sleep(1)
    finally:
      lock.release()

t1 = threading.Thread(target=action_one, name='子线程1')
t2 = threading.Thread(target=action_two, name='子线程2')
t1.start()
t2.start()
t1.join()
t2.join()

进程之间和线程之间的相互协调

1.进程间的通信:

  Process之间肯定是需要通信的,操作系统提供了很多机制来实现进程间的通信。Python的multiprocessing模块包装了底层的机制,提供了Queue、Pipes等多种方式来交换数据。

  以Queue为例,在父进程中创建两个子进程,一个往Queue里写数据,一个从Queue里读数据:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from multiprocessing import Process, Queue
import os, time, random

# 写数据进程执行的代码:
def write(q):
  print('Process to write: %s' % os.getpid())
  for value in ['A', 'B', 'C']:
    print('Put %s to queue...' % value)
    q.put(value)
    time.sleep(random.random())

# 读数据进程执行的代码:
def read(q):
  print('Process to read: %s' % os.getpid())
  while True:
    value = q.get(True)
    print('Get %s from queue.' % value)

if __name__=='__main__':
  # 父进程创建Queue,并传给各个子进程:
  q = Queue()
  pw = Process(target=write, args=(q,))
  pr = Process(target=read, args=(q,))
  # 启动子进程pw,写入:
  pw.start()
  # 启动子进程pr,读取:
  pr.start()
  # 等待pw结束:
  pw.join()
  # pr进程里是死循环,无法等待其结束,只能强行终止:
  pr.terminate()

  在Unix/Linux下,multiprocessing模块封装了fork()调用,使我们不需要关注fork()的细节。由于Windows没有fork调用,因此,multiprocessing需要“模拟”出fork的效果,父进程所有Python对象都必须通过pickle序列化再传到子进程去,所有,如果multiprocessing在Windows下调用失败了,要先考虑是不是pickle失败了。

2.线程间通信

  1.Queue

  使用线程队列有一个要注意的问题是,向队列中添加数据项时并不会复制此数据项,线程间通信实际上是在线程间传递对象引用。如果你担心对象的共享状态,那你最好只传递不可修改的数据结构(如:整型、字符串或者元组)或者一个对象的深拷贝。

  Queue 对象提供一些在当前上下文很有用的附加特性。比如在创建 Queue 对象时提供可选的 size 参数来限制可以添加到队列中的元素数量。对于“生产者”与“消费者”速度有差异的情况,为队列中的元素数量添加上限是有意义的。比如,一个“生产者”产生项目的速度比“消费者”“消费”的速度快,那么使用固定大小的队列就可以在队列已满的时候阻塞队列,以免未预期的连锁效应扩散整个程序造成死锁或者程序运行失常。在通信的线程之间进行“流量控制”是一个看起来容易实现起来困难的问题。如果你发现自己曾经试图通过摆弄队列大小来解决一个问题,这也许就标志着你的程序可能存在脆弱设计或者固有的可伸缩问题。 get() 和 put() 方法都支持非阻塞方式和设定超时。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import queue

q = queue.Queue()
try:
  data = q.get(block=False)
except queue.Empty:
  ...
try:
  q.put(item, block=False)
except queue.Full:
  ...
try:
  data = q.get(timeout=5.0)
except queue.Empty:
  ...


def producer(q):
  ...
  try:
    q.put(item, block=False)
  except queue.Full:
    log.warning('queued item %r discarded!', item)
_running = True


def consumer(q):
  while _running:
    try:
      item = q.get(timeout=5.0)
      # Process item
      ...
    except queue.Empty:
      pass

  最后,有 q.qsize() , q.full() , q.empty() 等实用方法可以获取一个队列的当前大小和状态。但要注意,这些方法都不是线程安全的。可能你对一个队列使用empty() 判断出这个队列为空,但同时另外一个线程可能已经向这个队列中插入一个数据项。所以,你最好不要在你的代码中使用这些方法。

  为了避免出现死锁的情况,使用锁机制的程序应该设定为每个线程一次只允许获取一个锁。如果不能这样做的话,你就需要更高级的死锁避免机制。在 threading 库中还提供了其他的同步原语,比如 RLock 和 Semaphore 对象。

  Queue提供的方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
task_done()

  意味着之前入队的一个任务已经完成。由队列的消费者线程调用。每一个get()调用得到一个任务,接下来的task_done()调用告诉队列该任务已经处理完毕。

  如果当前一个join()正在阻塞,它将在队列中的所有任务都处理完时恢复执行(即每一个由put()调用入队的任务都有一个对应的task_done()调用)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
join()

  阻塞调用线程,直到队列中的所有任务被处理掉。

  只要有数据被加入队列,未完成的任务数就会增加。当消费者线程调用task_done()(意味着有消费者取得任务并完成任务),未完成的任务数就会减少。当未完成的任务数降到0,join()解除阻塞。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
put(item[, block[, timeout]])

  将item放入队列中。     1.如果可选的参数block为True且timeout为空对象(默认的情况,阻塞调用,无超时)。     2.如果timeout是个正整数,阻塞调用进程最多timeout秒,如果一直无空空间可用,抛出Full异常(带超时的阻塞调用)。     3.如果block为False,如果有空闲空间可用将数据放入队列,否则立即抛出Full异常

  其非阻塞版本为put_nowait等同于put(item, False)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
get([block[, timeout]])

  从队列中移除并返回一个数据。block跟timeout参数同put方法

  其非阻塞方法为get_nowait()相当与get(False)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
empty()

  如果队列为空,返回True,反之返回False

  2.同步机制Event

  线程的一个关键特性是每个线程都是独立运行且状态不可预测。如果程序中的其他线程需要通过断某个线程的状态来确定自己下一步的操作,这时线程同步问题就会变得非常棘手。为了解决这些问题,我们需要使用 threading 库中的 Event 对象。

  Event 对象包含一个可由线程设置的信号标志,它允许线程等待某些事件的发生。在初始情况下,event 对象中的信号标志被设置假。如果有线程等待一个 event 对象,而这个 event 对象的标志为假,那么这个线程将会被一直阻塞直至该标志为真。一个线程如果将一个 event 对象的信号标志设置为真,它将唤醒所有等待个 event 对象的线程。如果一个线程等待一个已经被设置为真的 event 对象,那么它将忽略这个事件,继续执行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from threading import Thread, Event
import time

def countdown(n, start_evt):
  print('countdown is starting...')
  start_evt.set()
  while n > 0:
    print('T-minus', n)
    n -= 1
    time.sleep(5)

start_evt = Event() # 可通过Event 判断线程的是否已运行
t = Thread(target=countdown, args=(10, start_evt))
t.start()

print('launching countdown...')
start_evt.wait() # 等待countdown执行

# event 对象的一个重要特点是当它被设置为真时会唤醒所有等待它的线程

print('countdown is running...')

  Semaphore(信号量)   在多线程编程中,为了防止不同的线程同时对一个公用的资源(比如全部变量)进行修改,需要进行同时访问的数量(通常是1)的限制。信号量同步基于内部计数器,每调用一次acquire(),计数器减1;每调用一次release(),计数器加1.当计数器为0时,acquire()调用被阻塞。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from threading import Semaphore, Lock, RLock, Condition, Event, Thread
import time

# 信号量
sema = Semaphore(3) #限制同时能访问资源的数量为3

def foo(tid):
  with sema:
    print('{} acquire sema'.format(tid))
    time.sleep(1)
  print('{} release sema'.format(tid))


threads = []

for i in range(5):
  t = Thread(target=foo, args=(i,))
  threads.append(t)
  t.start()

for t in threads:
  t.join()

  Lock(锁)   互斥锁为资源引入一个状态:锁定/非锁定。某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。

  互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#创建锁
mutex = threading.Lock()
#锁定
mutex.acquire([timeout])
#释放
mutex.release()

  RLock(可重入锁)   为了支持在同一线程中多次请求同一资源,python提供了“可重入锁”:threading.RLock。RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次acquire。直到一个线程所有的acquire都被release,其他的线程才能获得资源。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import threading
import time

class MyThread(threading.Thread):
  def run(self):
    global num 
    time.sleep(1)

    if mutex.acquire(1): 
      num = num+1
      msg = self.name+' set num to '+str(num)
      print msg
      mutex.acquire()
      mutex.release()
      mutex.release()

num = 0
mutex = threading.RLock()


def test():
  for i in range(5):
    t = MyThread()
    t.start()

if __name__ == '__main__':
  test()

  Condition(条件变量)   Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还提供了wait和notify方法。线程首先acquire一个条件变量,然后判断一些条件。如果条件不满足则wait;如果条件满足,进行一些处理改变条件后,通过notify方法通知其他线程,其他处于wait状态的线程接到通知后会重新判断条件。不断的重复这一过程,从而解决复杂的同步问题。

  可以认为Condition对象维护了一个锁(Lock/RLock)和一个waiting池。线程通过acquire获得Condition对象,当调用wait方法时,线程会释放Condition内部的锁并进入blocked状态,同时在waiting池中记录这个线程。当调用notify方法时,Condition对象会从waiting池中挑选一个线程,通知其调用acquire方法尝试取到锁。

  Condition对象的构造函数可以接受一个Lock/RLock对象作为参数,如果没有指定,则Condition对象会在内部自行创建一个RLock。

  除了notify方法外,Condition对象还提供了notifyAll方法,可以通知waiting池中的所有线程尝试acquire内部锁。由于上述机制,处于waiting状态的线程只能通过notify方法唤醒,所以notifyAll的作用在于防止有线程永远处于沉默状态。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import threading
import time

class Producer:
  def run(self):
    global count
    while True:
      if con.acquire():
        if count > 1000:
          con.wait()
        else:
          count += 100
          msg = threading.current_thread().name + ' produce 100, count=' + str(count)
          print(msg)
          con.notify() # 通知 waiting线程池中的线程
        con.release()
        time.sleep(1)

count = 0
con = threading.Condition()

class Consumer:
  def run(self):
    global count
    while True:
    if con.acquire():
      if count < 100:
        con.wait()
      else:
        count -= 3
        msg = threading.current_thread().name + ' consumer 3, count=' + str(count)
        print(msg)
        con.notify()
      con.release()
      time.sleep(3)

producer = Producer()

进程和线程的比较

1.稳定性

  多进程模式最大的优点就是稳定性高,因为一个子进程崩溃了它拥有自己独立的内存空间,不会影响主进程和其他子进程(主进程崩掉,子进程也难逃厄运)。多进程模式的缺点是创建进程的代价大,在Unix/Linux系统下,用fork调用还行,在Windows下创建进程开销巨大。另外,操作系统能同时运行的进程数也是有限的,在内存和CPU的限制下,如果有几千个进程同时运行,操作系统连调度都会成问题。   多线程模式通常比多进程快,多线程模式致命的缺点就是任何一个线程挂掉都可能直接造成整个进程崩溃,因为所有线程共享进程的内存。

2.切换开销

  首先上下文切换就是从当前执行任务切换到另一个任务执行的过程。但是,为了确保下次能从正确的位置继续执行,在切换之前,会保存上一个任务的状态。   操作系统在切换进程或者线程时需要先保存当前执行的现场环境(CPU寄存器状态、内存页等),然后,把新任务的执行环境准备好(恢复上次的寄存器状态,切换内存页等),才能开始执行。这个切换过程虽然很快,但是也需要耗费时间。   但是线程的切换虚拟空间内存是相同的,但是进程切换的虚拟空间内存则是不同的。所以线程上下文切换比进程上下文切换快的多。同时,这两种上下文切换的处理都是通过操作系统内核来完成的。内核的这种切换过程伴随的最显著的性能损耗是将寄存器中的内容切换出。

3.计算密集型和IO密集型下的选择

  我们可以把任务分为计算密集型和IO密集型。   计算密集型任务的特点是要进行大量的计算,消耗CPU资源。IO密集型任务的特点是涉及到网络、磁盘IO,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成

对比维度

多进程

多线程

总结

数据共享、同步

数据共享复杂,需要用IPC;数据是分开的,同步简单

因为共享进程数据,数据共享简单,但也是因为这个原因导致同步复杂

各有优势

内存、CPU

占用内存多,切换复杂,CPU利用率低

占用内存少,切换简单,CPU利用率高

线程占优

创建销毁、切换

创建销毁、切换复杂,速度慢

创建销毁、切换简单,速度很快

线程占优

编程、调试

编程简单,调试简单

编程复杂,调试复杂

进程占优

可靠性

进程间不会互相影响

一个线程挂掉将导致整个进程挂掉

进程占优

分布式

适应于多核、多机分布式;如果一台机器不够,扩展到多台机器比较简单

适应于多核分布式

进程占优

(1)需要频繁创建销毁的优先用线程

  原因请看上面的对比。

  这种原则最常见的应用就是Web服务器了,来一个连接建立一个线程,断了就销毁线程,要是用进程,创建和销毁的代价是很难承受的

(2)需要进行大量计算的优先使用线程

  所谓大量计算,当然就是要耗费很多CPU,切换频繁了,这种情况下线程是最合适的。

  这种原则最常见的是图像处理、算法处理。

(3)强相关的处理用线程,弱相关的处理用进程

  什么叫强相关、弱相关?理论上很难定义,给个简单的例子就明白了。

  一般的Server需要完成如下任务:消息收发、消息处理。“消息收发”和“消息处理”就是弱相关的任务,而“消息处理”里面可能又分为“消息解码”、“业务处理”,这两个任务相对来说相关性就要强多了。因此“消息收发”和“消息处理”可以分进程设计,“消息解码”、“业务处理”可以分线程设计。

  当然这种划分方式不是一成不变的,也可以根据实际情况进行调整。

(4)可能要扩展到多机分布的用进程,多核分布的用线程

  原因请看上面对比。

我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2qkn8bupvco4o

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-08-22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
python进程vs线程
线程切换是有代价的,多任务一旦多到一个限度,就会消耗掉系统所有的资源,结果效率急剧下降,所有任务都做不好
测试加
2022/04/27
4190
Python教程第8章 | 线程与进程
在进程中,又可以创建一些线程,他们共享这些内存空间,并由操作系统调用,以便并行计算。
仲君Johnny
2024/01/24
1790
Python教程第8章 | 线程与进程
python 之进程与线程
从系统调度和资源分配的角度来看,进程是 CPU 资源分配的最小单位,线程是 CPU 调度的最小单位。从 CPU 执行时间的角度来看,进程是包含了上下文切换的程序执行时间总和,线程是共享了进程的上下文环境的更为细小的 CPU 时间段。
keinYe
2019/08/01
4060
python之线程、进程
    从列表中取一个数据,相当于是复制了一份列表中的数据,列表中的元数据并没有被改动
py3study
2020/01/03
3780
python多线程
1 多进程 # 多进程, import os import time from multiprocessing import Process # 启动时必须在 if __name__ 判断下,windows 必须,其他 无限制 # ================================================= # def func(args): # print("子进程:",os.getpid()) # print("子进程的父进程:",os.getppid()) #
Dean0731
2020/05/08
1.7K0
python多线程多进程脚本
python 中一般用 threading 模块来实现多线程,一种实现多线程的脚本如下,最终的运行时间为 1s 多一点点,join 表示将子线程加入主线程,等待子线程都运行完才会继续往下执行。
棒棒鸡不棒
2022/09/02
9330
Python之线程
操作系统线程理论 线程概念的引入背景 进程 之前我们已经了解了操作系统中进程的概念,程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。在多道编程中,我们允许多个程序同时加载到内存中,在操作系统的调度下,可以实现并发地执行。正是这样的设计,大大提高了CPU的利用率。进程的出现让每个用户感觉到自己独享CPU,因此,进程就是为了在CPU上实现多道编程而提出
新人小试
2018/04/12
1.4K0
Python之线程
Python与线程
进程在执行的过程中如果阻塞,例如等待输入,整个进程就会挂起,即使进程中有些工作不依赖于输入的数据,也将无法执行。
星陨1357
2023/03/14
3510
Python与线程
4.并发编程多线程
multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性,因而不再详细介绍
changxin7
2019/09/10
7400
Python学习记录-多进程和多线程
狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed)。 广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。
py3study
2020/01/07
8040
8.0 Python 使用进程与线程
python 进程与线程是并发编程的两种常见方式。进程是操作系统中的一个基本概念,表示程序在操作系统中的一次执行过程,拥有独立的地址空间、资源、优先级等属性。线程是进程中的一条执行路径,可以看做是轻量级的进程,与同一个进程中的其他线程共享相同的地址空间和资源。
王 瑞
2023/08/14
3520
一篇文章梳理清楚 Python 多线程与多进程
在学习Python的过程中,有接触到多线程编程相关的知识点,先前一直都没有彻底的搞明白。今天准备花一些时间,把里面的细节尽可能的梳理清楚。
吾非同
2021/12/13
1.1K0
一篇文章梳理清楚 Python 多线程与多进程
Python学习笔记(七)——进程和线程
很多时候,子进程并不是自身,而是一个外部进程。我们创建了子进程后,还需要控制子进程的输入和输出。
蛮三刀酱
2019/09/10
4050
Python学习笔记(十)·进程和线程
很多同学都听说过,现代操作系统比如Mac OS X,UNIX,Linux,Windows等,都是支持“多任务”的操作系统。
公爵
2022/09/28
5550
Python学习笔记(十)·进程和线程
Python 进阶(二):多进程
进程:通常一个运行着的应用程序就是一个进程,比如:我启动了一个音乐播放器,现在它就是一个进程。线程:线程是进程的最小执行单元,比如:我在刚启动的音乐播放器上选了一首歌曲进行播放,这就是一个线程。
Python小二
2020/08/18
4590
Python多进程、多线程、协程
在Unix/Linux中系统内核提供了fork系统调用来创建进程,根据不同的返回值来判断当前进程是子进程还是父进程,C语言代码示例如下:
chain
2018/06/05
2.6K14
Day15进程和线程
多进程 multiprocessing multiprocessing模块提供了一个Process类来代表一个进程对象,下面的例子演示了启动一个子进程并等待其结束: from multiprocessing import Process import os # 子进程要执行的代码 def run_proc(name): print('Run child process %s (%s)...' % (name, os.getpid())) # getpid是获得当前进程的进程号。系统每开辟一个新进程
林清猫耳
2018/04/26
5640
Python(十)
Python 既支持多进程,又支持多线程,本篇,我们看看如何编写这两种多任务程序。
1ess
2021/11/01
3610
python并发编程之多线程编程
一、threading模块介绍 multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性,因而不再详细介绍 二、开启线程的两种方式 方式一: from threading import Thread import time import random def task(name): print('%s is running' %name) time.sleep(random.rand
py3study
2020/01/07
4850
python网络爬虫(2)回顾Python编程
把内存中的数据变为可保存和共享,实现状态保存。cPickle使用C语言编写,效率高,优先使用。如果不存在则使用pickle。pickle使用dump和dumps实现序列化。
嘘、小点声
2019/07/31
6600
相关推荐
python进程vs线程
更多 >
LV.0
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验