同じプロセスのリソースで複数のスレッドが、異なるタスク:スレッド間の通信
演習1:デュアルスレッド化スレッドの安全性の問題が発生し、場所を追加するために同期コードを考えて、同期を使用することが必要である
要件を:銀行は口座にお金節約、お金を節約するためにアカウント誰を表示するために、どのくらいの預金
分析:
同じ銀行口座を操作する
二つの異なる操作を、メモリは、ディスプレイは、
二つの動作を同時に行うことができること
コード:
1 クラスバンク 2 { 3。 文字列名; // 名前保存 4。 INTのAMOUNT; 5 。6 // 操作がとら又は預金バンクすべきかどうか 。7 ボイド PUT(文字列名、int型AMOUNT) 。8 { 9 この .nameの= 名前; 10 この .amount = AMOUNT; 11 } 12である 13である ボイドテイク() 14 { 15 のSystem.out.println(この .nameの+ "---" + この.amount); 16 } 17 } 18 // 定義オブジェクトは、Runnableをを実現スレッドのタスクを設け 19の。 クラス入力を実装Runnableを 20であり 、{ 21である プライベート・バンクB; 22である // 保存コンストラクタリソースを確保するために使用され、同一のディスプレイ 23は 公衆入力(バンクB) 24 { 25 本 = .B B; 26である } 27 公共 ボイドRUN() 28 { 29 INT X = 0 ; 30 ながら、(真の) 31である { 32 IF(X == 0 ) 33である { 34である ( "ジョー・スミス"、100)b.put; 35 } 36 他 37 [ { 38であり ; b.put( "リシ"、200である) 39 } 40 // 0と1の間スイッチングが上昇2残りの部分に使用することができる 41は X =(X + 1)2%; 42れる } 43である } 44である } 45 46である // 定義オブジェクトは、タスクスレッド設定のRunnableを実装し 47 クラスに出力を実装Runnableを 48 { 49 のプライベート・バンクB; 50 // 使用コンストラクタ保証保存と同じリソース表示 51される パブリック出力(バンクB) 52は 、{ 53であり、 この .B = B; 54である } 55 公共 ボイドRUN() 56は 、{ 57は 、一方(真の) 58 { 59 b.take( ); 60 } 61である } 62である } 63であり、 64 クラスThreadDemo 65 { 66 公共 静的 ボイドメイン(文字列[]引数) 67 { 68 // 同一资源 69 バンクB = 新銀行(); 70 71 =に入力新しい入力(B)。 72 アウト=出力新しい出力(B); 73 74 // 75 スレッドT1は= 新しいスレッドを(で)。 76 スレッドT2 = 新しいスレッド(アウト)。 77 78 t1.start()。 79 t2.start()。 80 } 81 }
結果:
なぜ、スレッドセーフ表示されますか?
分析:
ソリューション:追加同期(同期)、どのような位置に追加する同期?
同期ロック原理を追加:コードが共有データ上で動作があり、同じ同期ロックの対象(同期のためのロック同期方法、そのような物体(本))
コード:
1 class Bank 2 { 3 String name;//存钱人名 4 int amount; 5 6 //同步方法的同步锁为,此类的对象(this) 7 synchronized void put(String name,int amount) 8 { 9 this.name=name; 10 this.amount=amount; 11 } 12 13 synchronized void take() 14 { 15 System.out.println(this.name+"---"+this.amount); 16 } 17 }
结果出现的效果与预想结果不同,预想结果是存一笔,显示一笔:
结果分析:
接下来,想法是:在t1中执行完成后就让t2执行
具体做法:
1、使用一个共享数据(flag)记录t1是否已执行
2、已执行就让t1等待(原因:防止t1再次获取CPU执行权),让t2执行
3、t2执行完成,t2等待,把t1设置成未执行状态(让t1获取CPU执行资格)
1 class Bank 2 { 3 private String name; 4 private int amount; 5 private boolean flag=false; 6 7 synchronized void put(String name,int amount) 8 { 9 //1、判断线程是否已执行,防止t1线程继续获取CUP执行权 10 if(flag) 11 try{this.wait();}catch(InterruptedException e){}//wait()方法,将线程存放在阻塞线程池中,释放CUP执行权和释放同步锁 12 13 this.name=name; 14 this.amount=amount; 15 //已执行赋值 16 this.flag = true; 17 //唤醒阻塞线程池中的第一个线程,获取CUP执行资格 18 this.notify(); 19 } 20 21 synchronized void take() 22 { 23 if(!flag) 24 try{this.wait();}catch(InterruptedException e){} 25 System.out.println(this.name+"---"+this.amount); 26 27 this.flag = false; 28 this.notify(); 29 } 30 }
结果: