线程的创建和其他属性方法,线程的数据共享,互斥锁

今日寄语

永远不要高估自己

复习内容

操作系统的调度算法:
时间片轮转法
 多级反馈队列

同步、异步(描述程序提交任务的方式)
同步:提交任务之后,原地等待任务的执行结果
 异步:提交任务之后,不等待任务的执行结果,直接执行下面的代码
阻塞、非阻塞(描述程序的运行状态)
阻塞:遇到IO操作 阻塞态
非阻塞:就绪态/运行态
 
需要掌握:进程的三状态转换图

进程理论:
创建进程的本质:创建一块独立的内存空间

今日内容

1、进程间通信:IPC机制
2、生产者消费者模型(******)
3、线程理论
4、创建线程的两种方式
5、同一进程下的线程共享进程的所有数据
6、join方法
7、线程对象的其他属性和方法
8、守护线程
9、线程互斥锁

一、进程间通信:IPC机制

队列:先进先出
堆栈:先进后出

利用队列实现进程间的通信

队列的创建:
from multiprocessing import Queue:
 q = Queue(3)  # 创建了队列对象,并规定只能存储3个数据
 '''
# 存取数据
q.put(obj) # 往队列中放入数据
q.put(obj)
q.put(obj)
q.put(obj)
# 由于规定只能存储3个,所以这一行代码会堵塞住,等待从队列中取出一个数据,腾出空间来put数据
'''
 q.put_nowait(obj)  # 队列不满,跟put一样放入值,一旦队列满了,直接报错,不等待取出
 print(q.full())  # 判断队列是否满了,是则True,否则False
 
 '''
res = q.get() # 从队列中取出数据,可以赋值
res = q.get()
res = q.get()
res = q.get()
# 因为队列中只有3个数据,所以这一行代码会堵塞住,等待往队列中put一个数据来get数据
'''
 q.get_nowait()  # 队列不为空则跟get一样取值,空的话直接报错,不等待put值
 print(q.empty())  # 判断队列为不为空,在并发时判断不准确
 
# 基于队列实现进程间通信 代码示例:
from multiprocessing import Process, Queue
def producer(q):
 q.put('hello')

def consumer(q):
 print(q.get())
 
if __name__ == '__main__':
 q = Queue()
 p1 = Process(target=producer, args=(q, ))
c1 = Process(target=consumer, args=(q, ))
p1.start()
 c1.start()
 

二、生产者消费者模型

生产者:产生数据的对象
消费者:处理数据的对象

将生产数据 处理数据 解耦合,处理数据不需要直接与生产数据环节沟通
定义一个队列,生产者将数据存进去,消费者取出来对数据进行处理, 两者通过队列进行沟通

# 代码示例
from multiprocessing import Process, JoinableQueue
import time, random

def produser(name, food, q):
 for i in range(1, 6):
   food = '%s%s' % (food, i)
   time.sleep(random.randint(1, 3))
   q.put(food)
   print('%s生产了%s' % (name, food))

def consumer(name, q):
 while True:
   res = q.get()
   time.sleep(random.randint(1, 3))
   print('%s吃了%s' % (name, res))
q.task_done()

if __name__ == '__main__':
 q = JoinableQueue(5)
 p1 = Process(target=produser, args=('egon', '包子', q))
 p2 = Process(target=produser, args=('owen', '油条', q))
 c1 = Process(target=consumer, args=('tank', q))
p1.start()
 p2.start()
 
 c1.daemon = True
 c1.start()
 
 p1.join()
 p1.join()
 q.join()
 
print('主')

三、线程理论

进程是资源单位
线程是执行单位

为什么要有线程:
线程创建时间短
 
 进程需要开辟内存空间和拷贝代码
而线程都不需要
 
开线程的开销远小于开进程

四、创建线程的两种方式

# 方法一:
from threading import Thread
import time

def task():
 print('线程1 is running' )
 time.sleep(1)
 print('线程1 is done')
 
t1 = Thread(target=task)
t1.start()
print('主')

# 方法二
from threading import Thread
import time

class MyThread(Thread):
 def run(self):
   print('线程1 is running' )
   time.sleep(1)
   print('线程1 is done')

t1 = MyThread()
t1.start()
print('主')

五、同一进程下的线程共享进程的所有数据

测试代码:
from threading import Thread

x = 100

def task():
 glbal x
 x = 666
 print(222, )
 
t1 = Thread(target=task)
t1.start()
print('主')
run==>
666

六、join方法

from threading import Thread
import time

def task():
 print('thread1 is running')
 time.sleep(2)
 print('thread2 is done')

t1 = Thread(target=task)
t1.start()
t1.join()
print('主')
run==>
thread1 is running
thread2 is done

七、线程对象的其他属性和方法

from threading import Thread, current_thread, active_count
import os, time

def task(name):
 print('%s is running' % name, current_thread().name, current_thread().getName())
 time.sleep(1)
 print('%s is done' % name)
 
def info(name):
 print('%s is running' % name, current_thread().name, current_thread().getName())
 time.sleep(1)
 print('%s is done' % name)
 
t1 = Thread(target=task, args=('egon', ))
t2 = Thread(target=info, args=('owen', ))
t1.start()
t2.start()
t1.join()
print(active_count())  # 查看目前存活的进程
print(os.getpid())
run==>
egon is running Thread-1 Thread-1
owen is running Thread-2 Thread-2
egon is done
owen is done
1
1502

八、守护线程

from threading import Thread
import time

def task(name):
   print('%s is running'%name)
   time.sleep(1)
   print('%s is over'%name)

if __name__ == '__main__':
   t = Thread(target=task,args=('王磊',))
   # t.daemon = True
   t.start()
   print('主')
run==>
王磊 is running

九、线程互斥锁

from threading import Thread,Lock
import time

mutex = Lock()  # 在要操作的数据上上锁
n = 100

def task():
   global n
   mutex.acquire()  # 制定抢锁位置
   tmp = n
   time.sleep(0.1)
   n = tmp -1
   mutex.release()  # 释放锁

t_list = []
for i in range(100):
   t = Thread(target=task)
   t.start()
   t_list.append(t)

for t in t_list:
   t.join()

print(n)

 

posted @ 2019-05-07 17:05  输诚  阅读(223)  评论(0编辑  收藏  举报