JAvaマルチスレッドによるリソース競合の解決


/**
 *         
 * 
 * DualSync.f()(        ) this  , g()    syncObject   
 *  synchronized 。  ,           。
 * 
 * @create @author Henry @date 2016-12-06 
 */
class DualSynch {
	private Object syncObject = new Object();

	public synchronized void f() {
		for (int i = 0; i < 5; i++) {
			System.out.print("f()");
			Thread.yield();
		}
	}

	public void g() {
		synchronized (syncObject) {
			for (int i = 0; i < 5; i++) {
				System.out.print("g()");
				Thread.yield();
			}
		}
	}
}
/**
 *   main()     f() Thread         ,  main()        g() 。
 *         ,          ,                  
 *       。
 * 
 * @create @author Henry @date 2016-12-06
 *
 */
public class SyncObject {
	/**
	 *        :
	 * g()f()g()f()g()f()g()f()g()f()
	 * @param args
	 */
	public static void main(String[] args) {
		final DualSynch ds = new DualSynch();
		new Thread() {
			public void run() {
				ds.f();
			};
		}.start();
		ds.g();
	}
}

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**       
 * 
 *                            。              ,
 *                          。      5          x
 *       ,           5   x      。   ,          
 *        。
 *               java.lang.ThreadLocal   ,    :
 * 
 * 
 * @create @author Henry @date 2016-12-06 
 *
 */
class Accessor implements Runnable{
	private final int id;
	public Accessor(int idn){
		this.id=idn;
	}

	@Override
	public void run() {
		while(!Thread.currentThread().isInterrupted()){
			ThreadLocalVariableHolder.increment();
			System.out.println(this);
			Thread.yield();
		}
	}
	@Override
	public String toString() {
		return "#"+id+": "+ThreadLocalVariableHolder.get() ;
	}
	
}

/**
 * 
 * ThreadLocal           。   ThreadLocal ,     get() set()  
 *          ,  ,get()                 , set()       
 *            ,           。increment() get()   
 * ThreadLocalVariableHolder       。  ,increment() get()     
 * synchronized ,  ThreadLocal          。
 * 
 *         ,                      ,           
 *       ,      ThreadLocalVariableHolder  。
 * 
 * @create @author Henry @date 2016-12-06 
 *
 */
public class ThreadLocalVariableHolder {
	private static ThreadLocal value=new ThreadLocal(){
		private Random rand=new Random(47);
		protected synchronized Integer initialValue(){
			return rand.nextInt();
		}
	};
	public static void increment(){
		value.set(value.get()+1);
	}
	public static int get(){
		return value.get();
	}
	public static void main(String[] args) throws Exception {
		ExecutorService exec =Executors.newCachedThreadPool();
		for (int i = 0; i < 5; i++) 
			exec.execute(new Accessor(i));
		TimeUnit.SECONDS.sleep(3);
		exec.shutdown();
	}
}

付録:ThreadLocalのJDKでの紹介は以下の通りです.
public class ThreadLocal
extends Object
このクラスは、スレッドローカル(thread-local)変数を提供します.これらの変数は、ある変数(getメソッドまたはsetメソッドによって)にアクセスする各スレッドに独自のローカル変数があり、変数の初期化コピーとは独立しているため、通常の対応物とは異なります.ThreadLocalインスタンスは、通常、あるスレッド(例えば、ユーザIDまたはトランザクションID)にステータスを関連付けるクラスのprivate staticフィールドです.
たとえば、次のクラスは、スレッドごとに一意のローカル識別子を生成します.スレッドIDは、UniqueThreadIdGenerator.getCurrentThreadId()が最初に呼び出されたときに割り当てられ、後続の呼び出しでは変更されません.
  import java.util.concurrent.atomic.AtomicInteger;

 public class UniqueThreadIdGenerator {

     private static final AtomicInteger uniqueId = new AtomicInteger(0);

     private static final ThreadLocal < Integer > uniqueNum = 
         new ThreadLocal < Integer > () {
             @Override protected Integer initialValue() {
                 return uniqueId.getAndIncrement();
         }
     };
 
     public static int getCurrentThreadId() {
         return uniqueId.get();
     }
 } // UniqueThreadIdGenerator
 

各スレッドは、スレッドがアクティブであり、ThreadLocalインスタンスがアクセス可能である限り、スレッドのローカル変数のコピーに対する暗黙的な参照を保持します.スレッドが消失すると、スレッドのローカルインスタンスのすべてのコピーがゴミ回収されます(これらのコピーに対する他の参照がない限り).