次のように問題を与えてください:
解決策は次のとおりです:
public class Demo_5 { public static void main(String[] args) { //创建一个窗口 TicketWindow tw1=new TicketWindow(); //使用三个线程同时启动 Thread t1=new Thread(tw1); Thread t2=new Thread(tw1); Thread t3=new Thread(tw1); t1.start(); t2.start(); t3.start(); } } //售票窗口类 class TicketWindow implements Runnable{ private int nums=2000; //一共2000张票 @Override public void run() { while(true){ if(nums>0){ //先判断是否还有票 //Thread.currentThread().getName()得到当前线程的名字 System.out.println(Thread.currentThread().getName()+"在售出第"+nums+"张票"); //显示售票信息 //出票的速度是一秒出一张 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } nums--; }else{ break; //售票结束 } } } }
このコードを実行して問題を見つけてください。つまり、同じチケット番号が複数のチケット窓口で販売されている可能性があり、問題のあるコードはif else ステートメント ブロック。
解決策は、同期する必要があるコードセグメントで synchronized(Object){同期したいコード} を使用することです。
修正したコードは以下の通りです:
public class Demo_5 { public static void main(String[] args) { //创建一个窗口 TicketWindow tw1=new TicketWindow(); //使用三个线程同时启动 Thread t1=new Thread(tw1); Thread t2=new Thread(tw1); Thread t3=new Thread(tw1); t1.start(); t2.start(); t3.start(); } } //售票窗口类 class TicketWindow implements Runnable{ private int nums=2000; //一共2000张票 @Override public void run() { while(true){ //认为if else这段代码要保证其原子性(同步代码块) synchronized (this) { if(nums>0){ //先判断是否还有票 //Thread.currentThread().getName()得到当前线程的名字 System.out.println(Thread.currentThread().getName()+"在售出第"+nums+"张票"); //显示售票信息 //出票的速度是一秒出一张 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } nums--; }else{ break; //售票结束 } } } } }
このコードを実行すると、チケットが正常に発行されることが分かりました。
スレッド 1 は、同期する必要があるコードを実行しています。スレッド 2、3、4... は、トイレに行く前にドアを閉めて (ロックして) トイレに行くのと同じように、ブロックされてスレッド待機プールに入れられます。完了すると (ロックが解除され)、他の人が引き続き使用できるようになります。
以上がJava のスレッド セーフティの問題の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。