进程和线程的异同点
相同点: a) 每个进程都有一个进程控制块,线程也拥有一个线程控制块
b)二者都具有ID,一组寄存器,状态,优先级以及所要遵循的调度策略
不同点:
1.起源不同:
先有进程,后面再有线程
2.概念不同
进程: 进程是程序真正运行起来的实例,是系统分配资源与调度的基本单位
线程: 是CPU调度的基本单位
3.内存共享方式不同
进程: 操作系统给不同进程分配一定的内存,不同进程的内存通常不共享。除非使用进程间通信xx
线程: 一个进程里的线程同属于同一个进程,进程间内存共享的,只考虑如何协作分配的问题即可。
4.拥有的资源不同
1.不同线程共享的内容包括:
(1)进程代码段
(2)进程的共有数据
2.不同线程独有的内容包括:
(1)线程ID
(2)线程的堆栈
5.数量不同
一个进程至少包括一个进程,也可以包括多个线程
6.开销不同
(1)线程的创建、中指时间比进程短
(2)同一进程内的线程切换时间 比 进程切换短
(3)同一进程的各个线程间共享内存和文件资源,可以不通过内核进行通信。
云计算
概念:云计算是通过互联网分布计算服务
特点:自由按需访问;网络的泛在访问;快速弹性;可计量的服务;资源共享
架构:前端和后端(图)
给出计算pi的方式,如何实现并行
from mpi4py import MPI
N = 100000
w = 1/N
pi = 0
comm = MPI.COMM_WORLD #通信器
taskid = comm.Get_rank() #提供进程的序号
tasknum = comm.Get_size() #线程总数
for i in range(taskid, N, tasknum):
local = (i+0.5)*w
temp = 4/(1+local**2)*w
pi += temp
# comm.Reduce(local,pi,Op=MPI.SUM,root=0) #归约操作
pi = comm.gather(local,root=0) #gather函数聚合通信
if taskid == 0:
print(pi)
死锁复现
from mpi4py import MPI
comm = MPI.COMM_WORLD #通信器
taskid = comm.Get_rank() #提供进程的序号
tasknum = comm.Get_size() #线程总数
if taskid == 1:
d5 = comm.recv(5)
comm.send("hello 5", 5)
print("task 1 done")
if taskid == 5:
d1 = comm.recv(1)
comm.send("hello 1",1)
print("task 5 done")
bcast广播通信
from mpi4py import MPI
import time
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
var_share = 0
for i in range(10):
if rank == 0:
var_share += 100
else:
time.sleep(1)
var_share = comm.bcast(var_share,root=0)
var = var_share + rank
print(rank, "--->", var_share, "--->", var)
mpiexec -n 50 python src/chap4/bcast-test.py
N皇后问题(未完成)
from mpi4py import MPI
def move_to_right(board: list, rank):
if board[rank] != len(board)-1:
board[rank] += 1
else:
board[rank] = 1
def chk_broad(board,rank):
for row,col in enumerate(board):
if row != 0 and row != rank:
if col == board[rank]:
return True
elif abs(row-rank) == abs(col-board[rank]):
return True
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
board = []
if rank == 0:
pass
else:
if chk_broad(board, rank):
move_to_right()
H20生成
from threading import Semaphore,Lock
class H2O:
def __init__(self):
self.O = Semaphore(1)
self.H = Semaphore(2)
self.H2O = threading.Barrier(3)
def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:
self.H.acquire()
releaseHydrogen()
self.H2O.wait()
self.H.release()
def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:
self.O.acquire()
releaseOxygen()
self.H2O.wait()
self.O.release()
哲学家就餐
方法:一个一个串行吃
from threading import Lock
class DiningPhilosophers:
def __init__(self):
self.lock = Lock()
# call the functions directly to execute, for example, eat()
def wantsToEat(self,
philosopher: int,
pickLeftFork: 'Callable[[], None]',
pickRightFork: 'Callable[[], None]',
eat: 'Callable[[], None]',
putLeftFork: 'Callable[[], None]',
putRightFork: 'Callable[[], None]') -> None:
self.lock.acquire()
pickLeftFork()
pickRightFork()
eat()
putLeftFork()
putRightFork()
self.lock.release()
交替打印字符串
from threading import Semaphore
class FizzBuzz:
def __init__(self, n: int):
self.n = n
self.sem_fizz = Semaphore(0)
self.sem_buzz = Semaphore(0)
self.sem_fibu = Semaphore(0)
self.sem_num = Semaphore(1)
# printFizz() outputs "fizz"
def fizz(self, printFizz: 'Callable[[], None]') -> None:
for i in range(1, self.n+1):
if i % 3 == 0 and i % 5 != 0:
self.sem_fizz.acquire()
printFizz()
self.sem_num.release()
# printBuzz() outputs "buzz"
def buzz(self, printBuzz: 'Callable[[], None]') -> None:
for i in range(1, self.n+1):
if i % 3 != 0 and i % 5 == 0:
self.sem_buzz.acquire()
printBuzz()
self.sem_num.release()
# printFizzBuzz() outputs "fizzbuzz"
def fizzbuzz(self, printFizzBuzz: 'Callable[[], None]') -> None:
for i in range(1, self.n+1):
if i % 3 == 0 and i % 5 == 0:
self.sem_fibu.acquire()
printFizzBuzz()
self.sem_num.release()
# printNumber(x) outputs "x", where x is an integer.
def number(self, printNumber: 'Callable[[int], None]') -> None:
for i in range(1, self.n+1):
self.sem_num.acquire()
if i % 3 == 0 and i % 5 == 0:
self.sem_fibu.release()
elif i % 3 == 0:
self.sem_fizz.release()
elif i % 5 == 0:
self.sem_buzz.release()
else:
printNumber(i)
self.sem_num.release()
按序打印
import threading
class Foo:
def __init__(self):
self.f1 = threading.Event()
self.f2 = threading.Event()
def first(self, printFirst: 'Callable[[], None]') -> None:
printFirst()
self.f1.set()
def second(self, printSecond: 'Callable[[], None]') -> None:
self.f1.wait()
printSecond()
self.f2.set()
def third(self, printThird: 'Callable[[], None]') -> None:
self.f2.wait()
printThird()
交替打印FooBar
两个不同的线程将会共用一个 FooBar 实例:
- 线程 A 将会调用 foo() 方法,而
- 线程 B 将会调用 bar() 方法
请设计修改程序,以确保 “foobar” 被输出 n 次。
import threading
class FooBar:
def __init__(self, n):
self.n = n
self.foo_done = threading.Event()
self.bar_done = threading.Event()
def foo(self, printFoo: 'Callable[[], None]') -> None:
self.bar_done.set()
for i in range(self.n):
self.bar_done.wait()
# printFoo() outputs "foo". Do not change or remove this line.
printFoo()
self.bar_done.clear()
self.foo_done.set()
def bar(self, printBar: 'Callable[[], None]') -> None:
for i in range(self.n):
self.foo_done.wait()
# printBar() outputs "bar". Do not change or remove this line.
printBar()
self.foo_done.clear()
self.bar_done.set()
打印零与奇偶数
import threading
class ZeroEvenOdd:
def __init__(self, n):
self.n = n
self.e0 = threading.Event()
self.e1 = threading.Event()
self.e2 = threading.Event()
def zero(self, printNumber) -> None:
self.e0.set()
for i in range(1,self.n+1):
self.e0.wait()
printNumber(0)
self.e0.clear()
if i%2==0:
self.e2.set()
else:
self.e1.set()
def even(self, printNumber) -> None:
for i in range(2,self.n+1,2):
self.e2.wait()
printNumber(i)
self.e2.clear()
self.e0.set()
def odd(self, printNumber) -> None:
for i in range(1,self.n+1,2):
self.e1.wait()
printNumber(i)
self.e1.clear()
self.e0.set()