操作系統中線程和進程的概念:
進程是指一個內存中運行的應用程序,每個進程都有自己獨立的一塊內存空間,一個進程中可以啟動多個線程。
比如在Windows系統中,一個運行的exe就是一個進程。
動態性:進程的實質是程序的一次執行過程,進程是動態產生,動態消亡的
並發性:任何進程都可以同其他進程一起並發執行
獨立性:進程是一個能獨立運行的基本單位,同時也是系統分配資源和調度的獨立單位
異步性:每個進程都以相互獨、不可預知的速度向前推進
結構特征:進程由程序、數據和進程控制塊三部分組成。
線程是指進程中的一個執行流程,一個進程中可以運行多個線程。
比如java.exe進程中可以運行很多線程。線程總是屬於某個進程,進程中的多個線程共享進程的內存。
線程的五種狀態:
新生狀態(New):當一個線程的實例被創建即使用new關鍵字和Thread類或其子類創建一個線程對象后,
此時該線程處於新生狀態。 此時線程不是活着的(not alive);
就緒狀態(Runnable):通過調用線程實例的start()方法來啟動線程使線程進入就緒狀態;
但還沒有被分配到CPU,處於線程就緒隊列;此時線程是活着的(alive);
運行狀態(Running):一旦獲取CPU,線程就進入運行狀態,線程的run()方法才開始被執行;
如果在給定的時間內沒有執行結束,就會被系統給換下來回到線程的就緒狀態;
此時線程是活着的(alive);
阻塞狀態(Blocked):通過調用join()、sleep()、wait()或者資源被暫用使線程處於阻塞狀態;
此時線程是活着的(alive)
死亡狀態(Dead):當一個線程的run()方法運行完畢或被中斷或被異常退出,該線程到達死亡狀態。
處於Dead狀態調用start()方法,會出現異常
注:部分文檔上會出現四種狀態的說法,實際上是把“就緒狀態”+“運行狀態”=可執行狀態
關於對象鎖:
一段synchronized的代碼被一個線程執行之前,他要先拿到執行這段代碼的權限,在java里邊就是拿到某個同步對象的鎖(一個對象只有一把鎖);
如果這個時候同步對象的鎖被其他線程拿走了,他(這個線程)就只能等了(線程阻塞在鎖池等待隊列中)。
取到鎖后,他就開始執行同步代碼(被synchronized修飾的代碼);線程執行完同步代碼后馬上就把鎖還給同步對象,
其他在鎖池中等待的某個線程就可以拿到鎖執行了同步代碼。這樣就保證了同步代碼在統一時刻只有一個線程在執行。
即:一個線程拿到了什么樣的對象鎖,就能打開什么樣的synchronized,而同一對象鎖只能在一個線程的手中
死鎖:當兩個線程相互等待對方釋放“鎖”時就會發生死鎖。
如何避免死鎖
1 使用事務時,盡量縮短事務的邏輯處理過程,及早提交或回滾事務;
2 設置死鎖超時參數為合理范圍,如:3分鍾-10分種;超過時間,自動放棄本次操作,避免進程懸掛;
3 優化程序,檢查並避免死鎖現象出現;
4 .對所有的腳本和SP都要仔細測試,在正式版本之前。
5 所有的SP都要有錯誤處理(通過@error)
6 一般不要修改SQL SERVER事務的默認級別。不推薦強行加鎖
可重入鎖的概念是 自己可以再次獲得自己的內部鎖
重進入的實現是通過每個鎖關聯一個請求計數和一個占有它的線程,當計數為0時,認為鎖是未被占有的,線程請時求一個未被占有的鎖,
jvm將記錄鎖的占有者,並將請求計數置為一,如果同一個線程再次請求,計數器將遞增,每次占用線程退出同步塊計數器值將遞減,
直到計數器為0,鎖釋放,如果內部鎖不是可重入的,代碼將死鎖
