程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 去故就新 Java線程新同步機制(1)

去故就新 Java線程新同步機制(1)

編輯:關於JAVA

1、可重入鎖ReentrantLock,相當於synchronized塊,為臨界區提供互斥訪問機制。

(1) 相關的接口

創建一個可重入鎖

  1. Lock lock = new ReentrantLock();

請求鎖,如果鎖被當前另一個線程持有,則阻塞。

  1. void lock();

釋放鎖

  1. void unlock();

非阻塞型lock()

  1. boolean tryLock();


(2) 使用基本結構

  1. locker.lock();
  2. try{
  3. //code here to Access the cirtical section
  4. }finally{
  5. locker.unlock();
  6. }

這種結構保證在任何時刻只有一個線程能夠進入臨界區,如果一個線程鎖住了鎖對象,其他任何線程在調用lock時,都會被阻塞,直到第一個線程釋放鎖對象。而且無論try塊是否拋出異常,都會執行finally block,解鎖locker。

(3) 鎖的可重入性

鎖是可重入的,線程能夠重復地獲取它已經擁有的鎖。鎖對象維護一個持有計數(hold count)來追蹤對lock方法的嵌套調用。線程在每次調用lock後都要調用unlock來釋放鎖。由於這個特性,被一個鎖保護的代碼可以調用另一個使用相同鎖的方法。

(4) 示例代碼:

  1. import Java.util.concurrent.locks.Lock;
  2. import Java.util.concurrent.locks.ReentrantLock;
  3. class WorkerOne extends Thread{
  4. private Lock locker;
  5. public WorkerOne (Lock locker){
  6. this.locker = locker;
  7. }
  8. public void run(){
  9. locker.lock();
  10. try{
  11. System.out.println(Thread.currentThread().getName()+":step into critical section");
  12. }finally{
  13. locker.unlock();
  14. }
  15. }
  16. }
  17. class WorkerTwo extends Thread{
  18. private Lock locker;
  19. public WorkerTwo (Lock locker){
  20. this.locker = locker;
  21. }
  22. public void sayHello(){
  23. locker.lock();
  24. try{ System.out.println(Thread.currentThread().getName()+":call sayHello()");
  25. Thread.sleep(1000);
  26. } catch (InterruptedException e) {
  27. e.printStackTrace();
  28. }finally{
  29. locker.unlock();
  30. }
  31. }
  32. public void run(){
  33. locker.lock();
  34. try{ System.out.println(Thread.currentThread().getName()+":setp into critical section");
  35. //測試鎖的可重入性
  36. sayHello();
  37. }finally{
  38. locker.unlock();
  39. }
  40. }
  41. }
  42. public class Test5 {
  43. public static void main(String[] args) {
  44. Lock locker = new ReentrantLock();
  45. WorkerOne wo= new WorkerOne(locker);
  46. wo.setName("WorkerOne");
  47. WorkerTwo wt = new WorkerTwo(locker);
  48. wt.setName("WorkerTwo");
  49. wt.start();
  50. wo.start();
  51. }
  52. }

輸出:

WorkerTwo:setp into critical section
WorkerTwo:call sayHello()
WorkerOne:step into critical section

2、條件對象Condition,相當於wait-notify機制,提供一種線程間的等待通知機制,condition中的等待-通知方法是await(),signal(),signalAll(),也需要在互斥環境下被調用。

(1) 相關的接口

創建Condition對象,Condition對象是跟Lock關聯在一起的。

  1. Lock locker = new ReentrantLock();
  2. Condition cond = locker.newCondition();

把此線程放到條件的等待集中。

  1. void await();

解除此條件的等待集中所有線程的阻塞狀態。

  1. void signalAll();

在此條件的等待集中隨機選擇一個線程,解除其阻塞狀態。

  1. void signal();


(2) 使用的基本結構:

  1. //初始時ok_to_proceed為false.
  2. locker.lock()
  3. try{
  4. while(!ok_to_proceed){
  5. //進入等待此條件集中,被阻塞,它維持狀態直到另一個線程調用同一個條件上的。
  6. //signalAll/signal方法時為止。
  7. cond.await();
  8. }
  9. }finally{
  10. cker.unlock();
  11. }
  1. locker.lock();
  2. try{
  3. //調用將解除所有等待此條件下的線程的阻塞狀態。當線程從等待集中被移走時,它們將再次成為可運行的,調度器將再次激活它們
  4. //此時,它們將試圖重新進入對象。一旦鎖可獲得,它們中的某個線程將從await調用返回,從而獲得鎖並從它被阻塞的地方繼續執行。
  5. ok_to_proceed = true;
  6. cond.signalAll() or cond.signal();
  7. }finally{
  8. locker.unlock();
  9. }

ok_to_proceed也是為了防止wait-notify出現的問題,即再wait之間,notify()已經給出通知,此時wait只會一直等待下去,這樣就保證了signal()線程的通知被await()線程接收到。

(3) 測試代碼:

  1. import Java.util.concurrent.locks.Condition;
  2. import Java.util.concurrent.locks.Lock;
  3. import Java.util.concurrent.locks.ReentrantLock;
  4. class GlobalV{
  5. public final static Lock locker = new ReentrantLock();
  6. public final static Condition cond = locker.newCondition();
  7. public static boolean to_proceed = false;
  8. }
  9. class Response extends Thread{
  10. public void run(){
  11. while(true){
  12. GlobalV.locker.lock();
  13. try{
  14. while(!GlobalV.to_proceed){
  15. GlobalV.cond.await();
  16. }
  17. System.out.println("Response:finish a job");
  18. GlobalV.to_proceed = false;
  19. }catch(Exception e){
  20. e.printStackTrace();
  21. }finally{
  22. GlobalV.locker.unlock();
  23. }
  24. }
  25. }
  26. }
  27. class Request extends Thread{
  28. public void run(){
  29. while(true){
  30. GlobalV.locker.lock();
  31. try{
  32. GlobalV.to_proceed = true;
  33. GlobalV.cond.signalAll();
  34. System.out.println("Request:send a job to Response");
  35. }finally{
  36. GlobalV.locker.unlock();
  37. }
  38. try {
  39. Thread.sleep(2000);
  40. } catch (InterruptedException e) {
  41. e.printStackTrace();
  42. }
  43. }
  44. }
  45. }
  46. public class Test6 {
  47. public static void main(String[] args) {
  48. Request req = new Request();
  49. Response res = new Response();
  50. req.start();
  51. res.start();
  52. }
  53. }

輸出:

Request:send a job to Response
Response:finish a job
Request:send a job to Response
Response:finish a job
Request:send a job to Response
Response:finish a job
Request:send a job to Response
Response:finish a job
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved