美文网首页
2 线程与python

2 线程与python

作者: fancy_gogo | 来源:发表于2018-10-10 13:31 被阅读0次

1 全局解释器锁(GIL)

python代码执行是在python虚拟机上进行控制的,在主循环中同时只能有一个控制线程在执行,就像单核CPU系统中的多进程一样。python解释器可以运行多个线程,但在任意时刻只会有一个线程会被解释器执行。

对python虚拟机的访问是由全局解释器锁(GIL)进行控制的。这个锁保证同时只能有一个线程运行。在多线程环境下,python虚拟机将按以下方式执行:

1 设置GIL
2 切换进一个进程去执行
3 执行下面操作之一:
a 指定数量的字节码指令
b 线程主动让出控制权(可调用time.sleep(0)来完成)
4 把多线程设置回睡眠状态(切换出线程)
5 解锁GIL
6 重复以上动作。

2 threading是对thread的封装。

1、开启线程:
线程有2种调用方式,如下:

直接调用
import threading
import time
 
def sayhi(num): #定义每个线程要运行的函数
 
    print("running on number:%s" %num)
 
    time.sleep(3)
 
if __name__ == '__main__':
 
    t1 = threading.Thread(target=sayhi,args=(1,)) #生成一个线程实例
    t2 = threading.Thread(target=sayhi,args=(2,)) #生成另一个线程实例
 
    t1.start() #启动线程
    t2.start() #启动另一个线程
 
    print(t1.getName()) #获取线程名
    print(t2.getName())
继承式调用
import threading
import time

class MyThread(threading.Thread):
    def __init__(self,num):
        threading.Thread.__init__(self)
        self.num = num
 
    def run(self):#定义每个线程要运行的函数
 
        print("running on number:%s" %self.num)
 
        time.sleep(3)
 
if __name__ == '__main__':
 
    t1 = MyThread(1)
    t2 = MyThread(2)
    t1.start()
    t2.start()
2、主进程下开启子进程:
t=multiprocessing.Process(target=work)
t.start()

程序会先执行主程序的语句,再执行此子进程的目标函数work();

3、t.setDadmon()设置守护进程;必须在start()之前设置;如果为True则主程序不用等此线程结束后再结束主程序;

from threading import Thread, current_thread
import time
def foo():
    print(123)
    time.sleep(5)
    print('end123')

def bar():
    print(456)
    time.sleep(2)
    print('end456')  # 守护线程:非守护线程代码运行结束后就结束


t1 = Thread(target=foo)
t2 = Thread(target=bar)

t1.daemon = True
t1.start()
t2.start()

# t1.join()                #让主线程原地等待子线程运行完毕后才运行下面代码
print('main----')

t.join()        等待线程结束;
t.isAlive()        返回线程是否活动
t.getName()      返回线程名。
t.setName()      设置线程名。
threading.currentThread() 返回当前线程变量;
threading.enumerate() 返回一个包含正在运行线程的列表;
threading.activeCount() 返回正在运行的线程数量;
threading.Semaphore(5) 限制最大连接数为5,semaphore是一个acquire,release的计数器;

多线程用于IO密集型,如socket,爬虫,web
多进程用于计算密集型,如金融分析

4

4、同步锁

R=threading.Lock()
R.acquire()
'''
对公共数据的操作
'''
R.release()
import threading, time

def run1():
    print("grab the first part data")
    lock.acquire()
    global num
    num += 1
    lock.release()
    return num

def run2():
    print("grab the second part data")
    lock.acquire()
    global num2
    num2 += 1
    lock.release()
    return num2

def run3():
    lock.acquire()
    res = run1()
    print('--------between run1 and run2-----')
    res2 = run2()
    lock.release()
    print(res, res2)

if __name__ == '__main__':

    num, num2 = 0, 0
    lock = threading.RLock()
    for i in range(10):
        t = threading.Thread(target=run3)
        t.start()

while threading.active_count() != 1:
    print(threading.active_count())
else:
    print('----all threads done---')
    print(num, num2)

用于对共享资源同步访问的限制,只有当一个线程访问完毕后另一个线程才能访问。

5、信号量

信号量是一个计数器,当资源消耗时递减,当资源释放时递增。信号量比锁更灵活因为可以有多个线程,每个线程拥有有限资源的一个实例。

from atexit import register
from random import randrange
from threading import BoundedSemaphore, Lock, Thread
from time import sleep, ctime

lock = Lock()
MAX = 5
candytray = BoundedSemaphore(MAX)

def refill():
    lock.acquire()
    print('Refilling candy...', end=' ')
    try:
        candytray.release()
    except ValueError:
        print('full, skipping')
    else:
        print('OK')
    lock.release()

def buy():
    lock.acquire()
    print('Buying candy...', end=' ')
    if candytray.acquire(False):
        print('OK')
    else:
        print('empty, skipping')
    lock.release()

def producer(loops):
    for i in range(loops):
        refill()
        sleep(randrange(3))

def consumer(loops):
    for i in range(loops):
        buy()
        sleep(randrange(3))

def _main():
    print('starting at:', ctime())
    nloops = randrange(2, 6)
    print('THE CANDY MACHINE (full with %d bars)!' % MAX)
    Thread(target=consumer, args=(randrange(
        nloops, nloops+MAX+2),)).start() # buyer
    Thread(target=producer, args=(nloops,)).start() # vendor

@register
def _atexit():
    print('all DONE at:', ctime())

if __name__ == '__main__':
    _main()
6 生产消费问题和Queue/queue模块
from random import randrange
from time import sleep
from queue import Queue
from myThread3 import MyThread

def writeQ(queue):
    print('producing object for Q...', end='')
    queue.put('xxx', 1)
    print("size now", queue.qsize())

def readQ(queue):
    val = queue.get(1)
    print('consumed object from Q... size now', queue.qsize())

def writer(queue, loops):
    for i in range(loops):
        writeQ(queue)
        sleep(randrange(1, 4))

def reader(queue, loops):
    for i in range(loops):
        readQ(queue)
        sleep(randrange(2, 6))

funcs = [writer, reader]
nfuncs = range(len(funcs))

def main():
    nloops = randrange(2, 6)
    q = Queue(32)

    threads = []
    for i in nfuncs:
        t = MyThread(funcs[i], (q, nloops), \
            funcs[i].__name__)
        threads.append(t)

    for i in nfuncs:
        threads[i].start()

    for i in nfuncs:
        threads[i].join()

    print('all DONE')

if __name__ == '__main__':
    main()

相关文章

  • 5-线程(补充)

    Python多线程原理与实战 目的: (1)了解python线程执行原理 (2)掌握多线程编程与线程同步 (3)了...

  • 多线程

    Python多线程原理与实战 目的: (1)了解python线程执行原理 (2)掌握多线程编程与线程同步 (3)了...

  • 2 线程与python

    1 全局解释器锁(GIL) python代码执行是在python虚拟机上进行控制的,在主循环中同时只能有一个控制线...

  • 进程,线程,并行,并发,python 之 GIL详解

    主要内容:1.线程与进程2.并发与并行3.python GIL 1.进程与线程 进程:程序的一次执行 线程:CPU...

  • Python并发:多线程与多进程

    本篇概要 1.线程与多线程 2.进程与多进程 3.多线程并发下载图片 4.多进程并发提高数字运算 学习Python...

  • Python-线程、线程池

    1. Python多线程 python3中常用的线程模块为:_thread(Python2中的thread)、th...

  • Python(2)---并发编程

    目录 1. Python多线程与多进程知识1.1 并发与并行1.2 线程(thread)与进程(process)...

  • Python 多线程笔记

    Python 多线程笔记 创建线程 1. 使用函数创建多线程 2. 使用类创建多线程 继承 Thread 类 重写...

  • day1-Android使用Handler进行线程间通信

    1、子线程与子线程 2、子线程与主线程 xml

  • Python线程2

    函数_thread.start_new_thread创建一个线程,并且会立马返回一个无用的值 如果主进程结束,不管...

网友评论

      本文标题:2 线程与python

      本文链接:https://www.haomeiwen.com/subject/pedpaftx.html