學習了進程與線程,現對本身的學習進行記錄。html
目錄:python
一.進程與線程的概念,以及聯繫與區別程序員
二.多線程編程
三.python中多線程的應用服務器
四.python實例網絡
五.參考文獻數據結構
一.進程與線程的概念。以及聯繫與區別多線程
進程能夠被稱爲執行的程序,一個進程擁有完整的數據空間和代碼空間,每個進程的地址空間都是獨立的,進程之間不能共享數據。app
線程是進程的一部分,也能夠稱爲mini 進程。在同一個進程中的線程共用同一個地址空間,單有本身獨立的堆棧和局部變量。因此除了堆棧中的數據,其他全部數據均可以共享。socket
若是再形象點就引用一哥們的比喻,很形象:
好比一個公司,有不少不一樣的部門,每一個部門不在 同一個城市,而每一個部門都有許多的員工。
公司就比如是一個CPU,不一樣的部門就至關於不一樣的進程,他們是你幹你的,我幹個人,所利用的空間不一樣。想共享些什麼數據,須要email與傳真;而一個部門的每一個員工,至關於不一樣的線程,共在同一個部門,全部東西均可以共享。假如說一我的在用打印機,也就 是數據進入堆棧了,我再用打印機,你就用不了了,得等。
聯繫:
進程包括線程,能夠有一個或者多個
區別:
1.進程有獨立的地址空間,多進程較穩定,由於其中一個出現情況不影響另一個;同一個進程的多個線程,共用地址空間,多線程相比於多進程,穩定性要差,由於一個線程出現問題會嚴重影響其餘線程。
2.進程之間須要共享數據,要利用進程間通信;同一個進程中的線程不須要。
3.進程只是資源分配的最小單位;線程是執行的最小單位,也就是說實際執行的是線程。
二.多線程
我主要是針對多線程的學習,記錄以下。
多個線程運行在同一個進程中,線程之間能夠共享數據。每一個線程都有開始,順序執行和結束3部分,也就是在一個線程內部,代碼會按照順序依次執行的。它有一個本身的指令指針,記錄本身運行到什麼位置,線程在運行時可能被強佔或暫時的掛起。
線程中也要有一個主線程,該線程須要每一個線程要作什麼,線程須要什麼數據和參數,以及線程結束的時候,它們都提供了什麼結果,主線程能夠把各個線程的結果組成有意義的結果。
同一個進程中的線程之間能夠共享數據以及相互通信,但這種共享,也會帶來危險。若是多個線程共同訪問同一片數據,則頗有致使數據結果不一致的問題,這叫競態條件。由此大多數線程都帶有一系列的同步源語,來控制線程的執行和數據的訪問。
若是操做不當,就會產生死鎖,死鎖好比說有兩個線程x,y,都要利用資源A和B,線程x先得到到A,要獲取B,y先得到到B,要得到A,他倆都在等在資源,但誰都沒有丟掉本身已經得到的資源,這樣就陷入了互相無線等待的局面。
產生死鎖的條件:
1.互斥條件:多個線程不能同時使用統一資源。
2.請求與保持條件:一個線程必須擁有N個資源才能完成任務,它會一直佔用已經得到的資源部防守
3.不剝奪條件:對於某個線程已經得到的資源,其餘線程不能強行剝奪。
4.循環等待條件:若干進程之間造成一種頭尾相接的循環等待資源關係。
This constructor should always be called with keyword arguments. Arguments are:
group should be None; reserved for future extension when a ThreadGroup class is implemented.
target is the callable object to be invoked by the run() method. Defaults to None, meaning nothing is called.
name is the thread name. By default, a unique name is constructed of the form 「Thread-N」 where N is a small decimal number.
args is the argument tuple for the target invocation. Defaults to ().
kwargs is a dictionary of keyword arguments for the target invocation. Defaults to {}.
If not None, daemon explicitly sets whether the thread is daemonic. If None (the default), the daemonic property is inherited from the current thread.
If the subclass overrides the constructor, it must make sure to invoke the base class constructor (Thread.__init__()) before doing anything else to the thread.
Changed in version 3.3: Added the daemon argument.
Start the thread’s activity.
It must be called at most once per thread object. It arranges for the object’s run() method to be invoked in a separate thread of control.
This method will raise a RuntimeError if called more than once on the same thread object.
Method representing the thread’s activity.
You may override this method in a subclass. The standard run() method invokes the callable object passed to the object’s constructor as thetarget argument, if any, with sequential and keyword arguments taken from the args and kwargs arguments, respectively.
Wait until the thread terminates. This blocks the calling thread until the thread whose join() method is called terminates – either normally or through an unhandled exception –, or until the optional timeout occurs.
When the timeout argument is present and not None, it should be a floating point number specifying a timeout for the operation in seconds (or fractions thereof). As join() always returns None, you must call is_alive() after join() to decide whether a timeout happened – if the thread is still alive, the join() call timed out.
When the timeout argument is not present or None, the operation will block until the thread terminates.
A thread can be join()ed many times.
join() raises a RuntimeError if an attempt is made to join the current thread as that would cause a deadlock. It is also an error to join() a thread before it has been started and attempts to do so raise the same exception.
A string used for identification purposes only. It has no semantics. Multiple threads may be given the same name. The initial name is set by the constructor.
Old getter/setter API for name; use it directly as a property instead.
The ‘thread identifier’ of this thread or None if the thread has not been started. This is a nonzero integer. See the _thread.get_ident() function. Thread identifiers may be recycled when a thread exits and another thread is created. The identifier is available even after the thread has exited.
Return whether the thread is alive.
This method returns True just before the run() method starts until just after the run() method terminates. The module function enumerate() returns a list of all alive threads.
A boolean value indicating whether this thread is a daemon thread (True) or not (False). This must be set before start() is called, otherwiseRuntimeError is raised. Its initial value is inherited from the creating thread; the main thread is not a daemon thread and therefore all threads created in the main thread default to daemon = False.
The entire Python program exits when no alive non-daemon threads are left.
Old getter/setter API for daemon; use it directly as a property instead.
import time import threading array=[4,2,1] def Func(secs,k): time.sleep(secs) print 'No %d starts at'%k,time.ctime() lock=threading.Lock() class MyThread(threading.Thread): def __init__(self,secs): self.secs=secs super(MyThread,self).__init__() def run(self): lock.acquire() time.sleep(self.secs) print 'Done' lock.release() def main(): ths=[] Len=range(len(array)) for i in [2,3]: m=MyThread(i) ths.append(m) for i in range(2): print ths[i].getName() ths[i].start() ths[0].join() ths[1].join() print 'all done,ok! it costs:',time.clock() main()
RLock(可重入鎖)是一個能夠被同一個線程請求屢次的同步指令。RLock使用了「擁有的線程」和「遞歸等級」的概念,處於鎖定狀態時,RLock被某個線程擁有。擁有RLock的線程能夠再次調用acquire(),釋放鎖時須要調用release()相同次數。
能夠認爲RLock包含一個鎖定池和一個初始值爲0的計數器,每次成功調用 acquire()/release(),計數器將+1/-1,爲0時鎖處於未鎖定狀態。
構造方法:
RLock()
實例方法:
acquire([timeout])/release(): 跟Lock差很少。
Condition(條件變量)一般與一個鎖關聯。須要在多個Contidion中共享一個鎖時,能夠傳遞一個Lock/RLock實例給構造方法,不然它將本身生成一個RLock實例。
能夠認爲,除了Lock帶有的鎖定池外,Condition還包含一個等待池,池中的線程處於狀態圖中的等待阻塞狀態,直到另外一個線程調用notify()/notifyAll()通知;獲得通知後線程進入鎖定池等待鎖定。
構造方法:
Condition([lock/rlock])
實例方法:
acquire([timeout])/release(): 調用關聯的鎖的相應方法。
wait([timeout]): 調用這個方法將使線程進入Condition的等待池等待通知,並釋放鎖。使用前線程必須已得到鎖定,不然將拋出異常。
notify(): 調用這個方法將從等待池挑選一個線程並通知,收到通知的線程將自動調用acquire()嘗試得到鎖定(進入鎖定池);其餘線程仍然在等待池中。調用這個方法不會釋放鎖定。使用前線程必須已得到鎖定,不然將拋出異常。
notifyAll(): 調用這個方法將通知等待池中全部的線程,這些線程都將進入鎖定池嘗試得到鎖定。調用這個方法不會釋放鎖定。使用前線程必須已得到鎖定,不然將拋出異常。
例子是很常見的生產者/消費者模式:
Semaphore(信號量)是計算機科學史上最古老的同步指令之一。Semaphore管理一個內置的計數器,每當調用acquire()時-1,調用release() 時+1。計數器不能小於0;當計數器爲0時,acquire()將阻塞線程至同步鎖定狀態,直到其餘線程調用release()。
基於這個特色,Semaphore常常用來同步一些有「訪客上限」的對象,好比鏈接池。
BoundedSemaphore 與Semaphore的惟一區別在於前者將在調用release()時檢查計數器的值是否超過了計數器的初始值,若是超過了將拋出一個異常。
構造方法:
Semaphore(value=1): value是計數器的初始值。
實例方法:
acquire([timeout]): 請求Semaphore。若是計數器爲0,將阻塞線程至同步阻塞狀態;不然將計數器-1並當即返回。
release(): 釋放Semaphore,將計數器+1,若是使用BoundedSemaphore,還將進行釋放次數檢查。release()方法不檢查線程是否已得到 Semaphore。
Event(事件)是最簡單的線程通訊機制之一:一個線程通知事件,其餘線程等待事件。Event內置了一個初始爲False的標誌,當調用set()時設爲True,調用clear()時重置爲 False。wait()將阻塞線程至等待阻塞狀態。
Event其實就是一個簡化版的 Condition。Event沒有鎖,沒法使線程進入同步阻塞狀態。
構造方法:
Event()
實例方法:
isSet(): 當內置標誌爲True時返回True。
set(): 將標誌設爲True,並通知全部處於等待阻塞狀態的線程恢復運行狀態。
clear(): 將標誌設爲False。
wait([timeout]): 若是標誌爲True將當即返回,不然阻塞線程至等待阻塞狀態,等待其餘線程調用set()。
Timer(定時器)是Thread的派生類,用於在指定時間後調用一個方法。
構造方法:
Timer(interval, function, args=[], kwargs={})
interval: 指定的時間
function: 要執行的方法
args/kwargs: 方法的參數
實例方法:
Timer從Thread派生,沒有增長實例方法。
local是一個小寫字母開頭的類,用於管理 thread-local(線程局部的)數據。對於同一個local,線程沒法訪問其餘線程設置的屬性;線程設置的屬性不會被其餘線程設置的同名屬性替換。
能夠把local當作是一個「線程-屬性字典」的字典,local封裝了從自身使用線程做爲 key檢索對應的屬性字典、再使用屬性名做爲key檢索屬性值的細節。
熟練掌握Thread、Lock、Condition就能夠應對絕大多數須要使用線程的場合,某些狀況下local也是很是有用的東西。本文的最後使用這幾個類展現線程基礎中提到的場景:
Queue objects (Queue, LifoQueue, or PriorityQueue) provide the public methods described below.
Return the approximate size of the queue. Note, qsize() > 0 doesn’t guarantee that a subsequent get() will not block, nor will qsize() < maxsize guarantee that put() will not block.
Return True if the queue is empty, False otherwise. If empty() returns True it doesn’t guarantee that a subsequent call to put() will not block. Similarly, if empty() returns False it doesn’t guarantee that a subsequent call to get() will not block.
Return True if the queue is full, False otherwise. If full() returns True it doesn’t guarantee that a subsequent call to get() will not block. Similarly, if full() returns False it doesn’t guarantee that a subsequent call to put() will not block.
Put item into the queue. If optional args block is true and timeout is None (the default), block if necessary until a free slot is available. If timeout is a positive number, it blocks at most timeout seconds and raises the Full exception if no free slot was available within that time. Otherwise (block is false), put an item on the queue if a free slot is immediately available, else raise the Full exception (timeout is ignored in that case).
Equivalent to put(item, False).
Remove and return an item from the queue. If optional args block is true and timeout is None (the default), block if necessary until an item is available. Iftimeout is a positive number, it blocks at most timeout seconds and raises the Empty exception if no item was available within that time. Otherwise (block is false), return an item if one is immediately available, else raise the Empty exception (timeout is ignored in that case).
Equivalent to get(False).
Two methods are offered to support tracking whether enqueued tasks have been fully processed by daemon consumer threads.
Indicate that a formerly enqueued task is complete. Used by queue consumer threads. For each get() used to fetch a task, a subsequent call totask_done() tells the queue that the processing on the task is complete.
If a join() is currently blocking, it will resume when all items have been processed (meaning that a task_done() call was received for every item that had been put() into the queue).
Raises a ValueError if called more times than there were items placed in the queue.
Blocks until all items in the queue have been gotten and processed.
The count of unfinished tasks goes up whenever an item is added to the queue. The count goes down whenever a consumer thread calls task_done()to indicate that the item was retrieved and all work on it is complete. When the count of unfinished tasks drops to zero, join() unblocks.
import timeit 2 import threading 3 import sys 4 import os 5 6 def GetFileSize(filename): 7 8 FileSize=os.path.getsize(filename) 9 return FileSize 10 11 12 13 array=[] 14 lock=threading.Lock() 15 cur=0 16 sum=0 17 18 19 def Print_InColor(color,msg): 20 21 print '\033[0;%dm%s\033[0m' %(color,msg) 22 23 class MyThread(threading.Thread): 24 25 def __init__(self,filename): 26 27 self.filename=filename 28 super(MyThread,self).__init__() 29 30 def run(self): 31 32 global cur 33 global sum 34 Done=True 35 size=GetFileSize(self.filename) 36 f=file(self.filename,'r') 37 38 lock.acquire() 39 start=cur 40 Print_InColor(31,threading.currentThread().getName()) 41 Print_InColor(33,start) 42 length=start+int(size/3) 43 cur=end=length if length<size else size 44 Print_InColor(33,cur) 45 lock.release() 46 47 if start==size: 48 f.close() 49 50 f.seek(start,0) 51 print 'the new start position',f.tell(),self.getName() 52 53 while Done: 54 p=f.read(1) 55 c=f.tell() 56 if c>end: 57 print 'has ended,the posoition is ',c,self.getName() 58 Done=False 59 elif p=='i': 60 array.append(p) 61 sum+=1 62 #print sum 63 else: 64 continue 65 66 67 f.close() 68 69 70 71 def main(): 73 74 thds=[] 75 filename=sys.argv[1] 76 77 78 for i in range(3): 79 t=MyThread(filename) 80 thds.append(t) 81 82 for t in thds: 83 t.start() 84 85 for t in thds: 86 t.join() 87 88 89 90 91 92 if __name__=="__main__": 93 94 t=timeit.Timer("main()","from __main__ import main") 95 print t.timeit(1)
下一步計劃是實現多線程的socket服務器,Come on!
5、參考文獻
1.python核心編程
2.www.docs.python.org
3.python網絡編程基礎