Python进阶 - 进程与线程

1 Python下的进程编程

1.1 创建进程

  • system函数

原型如下:

system(command)

实际是调用系统内置的命令行程序来执行系统命令, 所以在命令结束之后会将控制权返回给Python进程。
如果返回0,说明执行成功,否则表示失败

  • exec家族

共有8个类似函数:execl, execle, execlp, execv, execve, execvp, execvpe
exec函数执行完命令之后,将会接管Python进程, 而不会将控制权返回给Python进程。也就是说,Python进程会在调用exec函数之后终止。新生成的进程将会替换主进程。这些函数没有返回值,如果发生错误,将会触发OSError异常

1.2 终止进程

  • sys.exit() 退出之前执行清理操作,更加优雅
  • sys.abort() 直接发出终止信号,在exit不能终止程序的时候用这个。

2 多线程编程

2.1 Python多线程简介

Python使用全局解释器锁(GIL)来保证解释其中仅有一个线程,并在各个线程之间切换。当GIL可用的时候,处于就绪状态的线程在获取GIL之后就可以运行了。线程将在指定的间隔时间内运行,时间到之后重新进入就绪队列排队。当然,特定的事件可能导致中断。

Python提供了两种不同的方式:

  • thread 低级的线程处理模块,仅提供最少的线程处理功能,在实际的代码中最好不要使用该模块
  • threading 高级的线程处理模块,基于thread模块,部分思想来自于Java的thread类

多线程的协调:

threading模块中提供了数据同步的方法。Queue模块中,有一个同步的FIFO队列,特别适于多线程的同步。

2.2 生成和终止线程

thread模块

常用方法:

  • start_new_thread 生成新线程,返回标识符的值
  • exit 退出,触发一个 SystemExit 异常
  • get_ident 获取标识符
  • allocate_lock 加锁
  • interrupt_main 在主线程中触发一个KeyboardInterrupt异常
  • stack_size 返回堆栈大小

示例程序:

import _thread
import time


def hello(index):
    for v in range(5):
        time.sleep(2)
        print("线程", v, index)


def test():
    _thread.start_new_thread(hello, (1,))
    _thread.start_new_thread(hello, (2,))


test()
time.sleep(15)

threading.thread类

常用方法:

  • start 允许进程实例
  • run 实现自己的线程时需要重载此方法
  • join 阻塞主线程,开始执行此线程
  • getName 返回线程名
  • setName 设置线程名
  • isAlive 查看线程是否运行
  • isDaemon 查看线程是否在后台运行
  • setDaemon 设置线程后台运行

使用示例:

import threading


def z():
    print("线程名:" + threading.current_thread().getName())


t1 = threading.Thread(target=z, name="my")
t1.start()

自定义Thread(继承自threading.thread)

import threading
import time
import random


class MyThread(threading.Thread):

    def __init__(self, name):
        threading.Thread.__init__(self, name=name)

    def run(self):
        for i in range(5):
            time.sleep(random.randint(1, 10))
            print("我是", self.name, "线程,第", i + 1, "次循环")


a = MyThread("A")
# a.setDaemon(True)
a.start()
b = MyThread("B")
# b.setDaemon(True)
b.start()
a.join()     # 加入join之后,先运行子线程,然后再执行之后的主线程代码!
b.join()
print("主线程退出,end!")

3 管理线程

线程状态转移:就绪、运行、休眠、终止

线程中的局部变量

import threading
import random
import time


class ThreadLocal():
    def __init__(self):
        self.local = threading.local()

    def run(self):
        time.sleep(random.random())
        self.local.number = []
        for i in range(10):
            self.local.number.append(random.choice(range(10)))
        print(threading.currentThread(), self.local.number)


ThreadLocal = ThreadLocal()
threads = []
for i in range(5):
    t = threading.Thread(target = ThreadLocal.run)
    t.start()
    threads.append(t)
for i in range(5):
    threads[i].join()

另一种:

import threading
import random
import time


class ThreadLocal(threading.Thread):
    def __init__(self, name):
        threading.Thread.__init__(self)
        self.local = threading.local()

    def run(self):
        time.sleep(random.random())
        self.local.number = []
        for i in range(10):
            self.local.number.append(random.choice(range(10)))
        print(threading.currentThread(), self.local.number)


threads = []
for i in range(5):
    t = ThreadLocal(str(i))
    t.start()
    threads.append(t)
for i in range(5):
    threads[i].join()

4 线程之间的同步

4.1 临界资源与临界区
4.2 锁机制

Lock:

import _thread
import time
mylock = _thread.allocate_lock()  # Allocate a lock
num = 0  # Shared resource


def add_num(name):
    global num
    while True:
        mylock.acquire()  # Get the lock
        # Do something to the shared resource
        print('Thread %s locked! num=%s' % (name, str(num)))
        if num >= 5:
            print('Thread %s released! num=%s' % (name, str(num)))
            mylock.release()
            num = 0
            _thread.exit_thread()
        num += 1
        print('Thread %s released! num=%s' % (name, str(num)))
        mylock.release()  # Release the lock.


def test():
    _thread.start_new_thread(add_num, ('A',))
    _thread.start_new_thread(add_num, ('B',))

if __name__ == '__main__':
    test()
    time.sleep(5)

RLock:

import threading
mylock = threading.RLock()
num = 0


class myThread(threading.Thread):

    def __init__(self, name):
        threading.Thread.__init__(self)
        self.t_name = name

    def run(self):
        global num  # 声明为全局变量
        while True:
            mylock.acquire()
            print('\nThread(%s) locked, Number: %d' % (self.t_name, num))
            if num >= 4:
                mylock.release()
                print('\nThread(%s) released, Number: %d' % (self.t_name, num))
                break
            num += 1
            print('\nThread(%s) released, Number: %d' % (self.t_name, num))
            mylock.release()


def test():
    thread1 = myThread('A')
    thread2 = myThread('B')
    thread1.start()
    thread2.start()

if __name__ == '__main__':
    test()

4.3 条件变量
4.4 信号量
4.5 同步队列

import threading
import queue    # Python3中将Queue改为了queue,千万注意!
import time
import random



class Worker(threading.Thread):
    def __init__(self, index, queue):
        threading.Thread.__init__(self)
        self.index = index
        self.queue = queue

    def run(self):
        while 1:
            time.sleep(random.random())
            item = self.queue.get()
            if item is None:
                break
            print("index", self.index, "task", item, "finished")
            self.queue.task_done()

q = queue.Queue()
for i in range(2):
    Worker(i, q).start()
for i in range(10):
    q.put(i)
for i in range(2):
    q.put(None)

你可能感兴趣的:(Python进阶 - 进程与线程)