Javaマルチスレッドシリーズ------同期関数と同期コードブロック


前回私たちは切符を売る問題で、一つの問題を投げ出した.私たちの4つのウィンドウ、つまり4つのスレッドが同時に切符を販売し始めると、共有リソースの奪い合い問題が発生します.共有リソースの奪取についてはコードが原子性ではないため数値的なエラーが発生した.では、この問題をどう解決すればいいのでしょうか.Javaのキーワードsynchronizedについて説明します.
まず、synchronizedは同期を意味するこのキーワードの意味を説明します.すなわちsynchronized修飾のコード範囲については,異なるスレッドがこの領域でのコード実行に前後順である.共有リソースの役割コードの範囲にsynchronizedを加えて修飾すれば、異なるスレッドが共有リソースを操作する際に優先順位を付けることができます.これにより、コードの正確性が保証されます.
具体的なコードを実装する前に、synchronizedキーワードの使用方法を知る必要があります.synchronizedはロックメカニズムであるという概念を明確にする必要がある.すなわち、スレッドが対応するsynchronized修飾のコードブロックを実行したい場合、synchronized修飾のオブジェクトまたはクラスのロックを取得する必要があるオブジェクトまたはクラスにロックを明記する必要があります.これがcpuの使用権です.ロックを取得してこそcpuにスケジューリングされ、処理権を得ることができる.synchronizedコードブロックの実行が終了すると、このスレッドは対応するロックを解放します.cpuはこのロックを他のスレッドに分けることができます.
同期ロックについては、実際には、同期関数と同期コードブロックの2つに分けることができます.
まず同期関数を見てみましょう.
   
public  synchronized void method() {}

ではsynchronizedがオブジェクトまたはクラスにロックをかける必要があることを知っていますが、この同期関数にロックをかけるロックは何ですか.この場所は明らかにthisオブジェクト、すなわち現在のオブジェクトにロックがかかっています.これはクラスメソッドで、クラスメソッドはオブジェクトに対応しています.オブジェクトをインスタンス化するときにのみ、メソッドに対応するメモリ領域が割り当てられます.クラスメソッドにロックを追加すると、このロックはthisに対応します.
public static synchronized void sale() {}

これ、静的方法を見てみましょう.synchronizedに対応するロックは何ですか.そう、クラスに対応する、このクラスのclassファイルです.
同期関数の話が終わると、同期コードブロックは簡単です.その鍵の対象は私たちが自分で決めることです
synchronized (obj) {



}

では、私たちの同期関数と同期コードブロックは交換できますか?もちろんできます.彼らの交換メカニズムは以下の通りで、具体的な理由はもう述べません.
public void synchronized method{}

synchronized(this){

}
public static void synchronized method(){}

synchronized(Class.class){
}

では、私たちの最初の問題に戻って、私はあなたがきっとこの問題を解決する方法を知っていると信じています.それはチケットの数の操作にsynchronizedキーワード修飾を加えればよいということです.
package com.zzu.my.thread.test.thread;

class SellTicket extends Thread{
	private static int tickets = 20;//    20  
	//                       ,               
	//run   
	@Override
	public void run(){
		while(true){
			if(tickets>0){
				System.out.println("  : "+Thread.currentThread().getName()+"    "+tickets--+"  ");
			}else{
				break;
			}
		}
	}
	
}
/**
 *       
 * @author Administrator
 *
 */
public class TicketDemo {

	public static void main(String[] args) {
		SellTicket t1 = new SellTicket();
		SellTicket t2 = new SellTicket();
		SellTicket t3 = new SellTicket();
		SellTicket t4 = new SellTicket();
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}

}

複数のスレッドに同じリソースを処理させるには、synchronized修飾オブジェクトが同じロックを使用する必要があります.そうでないと、異なるロックが発生し、2つのスレッドが同時に1つのリソースを読み取り、数値的なエラーが発生します.