線程---關於死鎖,進程和線程,多進程與多線程,synchronized與ReentrantLock的區別

怎麼理解系統的進程和線程??

進程:
進程是系統劃分資源(I/O資源[磁盤,文件],CPU資源,內存資源)的基本單位,進程本身不執行任何的指令;
每一個進程的創建,都伴隨着一個主線程的創建,線程纔是負責執行指令的,也就是說Linux系統調用的基本執行單元,就是線程(main線程 線程 = 線程棧(線程函數 main函數)),自己創建的線程,也是需要匹配一個線程的入口函數的,就是run函數;

線程:
線程是執行指令的單元,運行在一個進程的空間裏面的,線程沒有自己獨立的用戶空間。必須共享一個進程的用戶空間,每一個線程都有自己獨立的棧空間,他們共享一個進程的堆空間和.bss .data .text段;

爲什麼要寫多線程或者多進程程序?這兩者之間不同的地方??? 如何區分?

因爲現在的PC機或者服務器都是多核的CPU,一次可以併發執行多個線程,如果程序中還使用 單進程或者單線程,對CPU的資源是一種浪費,沒有有效的利益CPU的資源。

一般編寫多線程或者多進程的程序,線程或者進程的數量是和當前CPU的核心數量是一致的( 比如我看過的Apache mina或者netty網絡庫,就是這樣做的),這樣能發揮CPU多核的效率, 能夠讓多個進程或者線程併發執行。

由於進程佔用的資源比較大,而線程佔用的資源比較少,所有在多線程和多進程程序中,隨着CPU的調度,進程的上下文切換所花費的時間效率遠遠高於線程,因爲線程比較輕量,佔用資源少,所以上下文切換快,多進程程序,各進程之間進行數據共享,進程通信,進程互斥操作,非常複雜,不易實現;而線程 由於是共享進程空間的,所以共享堆和.bss .data.text;因此線程之間共享數據非常方便,通信也方便(wait/notify),線程互斥(鎖)都很方便。

所以大多數都使用多線程程序。

操作系統進程間通信的方式:匿名管道,命名管道,消息隊列,共享內存,信號量,套接字。

你見過哪些死鎖的問題??

  1. 多個線程,都在獲取多個鎖資源,但是獲取鎖資源的順序不同(可能會死鎖)

    ----》多個線程獲取鎖資源,加鎖解鎖的順序必須保持一致;

  2. 哲學家就餐問題:

    每一個哲學家(相當於一個線程)佔用了一個筷子資源,因爲得不到另外一支筷子資源,造成幾個線程相互等待對方釋放資源,因爲沒有線程釋放資源(筷子),造成整個系統死鎖;

  3. 多線程的生產者消費者模型:

    多線程程序,

線程間互斥:synchronized 與 ReentrantLock的區別:

(1)synchronized (java對象都有一個對象頭8個字節4字節+方法表的地址)

ReentrantLock java.util.concurrent.併發包JDK1.5)

synchronized效率太低,鎖太重;JDK1.6開始,對synchronized做了很大優化,可以實現輕量級鎖,偏向鎖,自旋鎖;

(2)synchronized是java的關鍵字,語言級別實現線程互斥;

ReentrantLock只是併發包concurrent包而提供的一個類,通過相應的方法調用 ,實現線程互斥;

(3)synchronized的加鎖解鎖是自動進行的,開發者不需要關心;

ReentrantLock必須手動調用lock和unlock方法進行加鎖解鎖操作,使用ReentrantLock一定要括在try finally塊裏面,在finally塊中調用unlock方法釋放併發鎖,防止死鎖發生;

(4)synchronized線程互斥,對讀讀,讀寫,寫寫都會進行互斥操作;

但是併發包裏面提供了專門的ReentrantReadWriteLock這個讀寫鎖;使得臨界區代碼段如果是讀讀操作,可以併發執行,但是讀寫和讀讀還是互斥執行的。

線程間的通信方式:共享內存和消息傳遞。

(1)volatile;(實現共享內存,多個線程同時監聽一個變量)

(2)Object.wait(), notify(),notifyAll():一般與synchronized連用,wait釋放鎖,notify獲取鎖;

(3)CountDownLatch類:java.util.concurrent包下的;

(4)ReentrantLock + Condition;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章