JAvaマルチスレッドによるリソース競合の解決
4046 ワード
/**
*
*
* 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インスタンスがアクセス可能である限り、スレッドのローカル変数のコピーに対する暗黙的な参照を保持します.スレッドが消失すると、スレッドのローカルインスタンスのすべてのコピーがゴミ回収されます(これらのコピーに対する他の参照がない限り).