Javaマルチスレッド-新しいフィーチャー-原子量
4334 ワード
いわゆる原子量,すなわち操作変数の操作は「原子的」であり,この操作は再分割できないためスレッドが安全である.なぜ原子変数を使用するのかは、複数のスレッドが単一の変数に対して操作してもいくつかの問題が発生するためです.Java 5の前にvolatile、synchronizedキーワードで同時アクセスのセキュリティ問題を解決できますが、これは面倒です.Java 5以降、単一変数マルチスレッドの同時セキュリティアクセスを行うためのツールパッケージjavaが提供する.util.concurrent.atomic、その中のクラスも簡単です.
実行結果から,原子量を用いたにもかかわらずプログラムの同時アクセスに問題があることが分かるが,それはいったいどこに問題があるのか.ここで注意しなければならないのは、原子量は、単一の変数の操作プロセスの安全を保証することができますが、コードブロック全体、またはプログラム全体の安全性を保証することはできません.したがって、通常、ロックなどの同期メカニズムを使用して、プログラム全体のセキュリティを制御する必要があります.次は、このエラーの修正です.
ここでは、同時コードへのアクセスを制御するオブジェクトロックを使用します.何回実行しても、実行順序にかかわらず、最終残高は21000であり、この結果は正しい.原子量の使い方は簡単で,原子量の認識が鍵であり,原子は変数操作の原子性を保証するだけであるが,プログラム全体はスレッドの安全を考慮する必要がある.
package cn.thread;
import java.util.concurrent.atomic.AtomicLong;
public class AtomicRunnable implements Runnable {
private static AtomicLong aLong = new AtomicLong(10000); // ,
private String name; //
private int x; //
AtomicRunnable(String name, int x) {
this.name = name;
this.x = x;
}
public void run() {
System.out.println(name + " " + x + ", :" + aLong.addAndGet(x));
}
}
package cn.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
/**
* -
*
* @author
* @version 1.0 2013-7-26 04:13:45
*/
public class ThreadAtomicTest {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(2);
Runnable t1 = new AtomicRunnable(" ", 2000);
Runnable t2 = new AtomicRunnable(" ", 3600);
Runnable t3 = new AtomicRunnable(" ", 2700);
Runnable t4 = new AtomicRunnable(" ", 600);
Runnable t5 = new AtomicRunnable(" ", 1300);
Runnable t6 = new AtomicRunnable(" ", 800);
//
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
pool.execute(t6);
//
pool.shutdown();
}
}
2000, :12000
2700, :14700
600, :15300
1300, :16600
800, :17400
3600, :21000
2000, :12000
3600, :15600
600, :18900
1300, :20200
800, :21000
2700, :18300
2000, :12000
2700, :14700
3600, :18300
1300, :20200
800, :21000
600, :18900
実行結果から,原子量を用いたにもかかわらずプログラムの同時アクセスに問題があることが分かるが,それはいったいどこに問題があるのか.ここで注意しなければならないのは、原子量は、単一の変数の操作プロセスの安全を保証することができますが、コードブロック全体、またはプログラム全体の安全性を保証することはできません.したがって、通常、ロックなどの同期メカニズムを使用して、プログラム全体のセキュリティを制御する必要があります.次は、このエラーの修正です.
package cn.thread;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
public class AtomicRunnable2 implements Runnable {
private static AtomicLong aLong = new AtomicLong(10000); // ,
private String name; //
private int x; //
private Lock lock;
AtomicRunnable2(String name, int x, Lock lock) {
this.name = name;
this.x = x;
this.lock=lock;
}
public void run() {
lock.lock();
System.out.println(name + " " + x + ", :" + aLong.addAndGet(x));
lock.unlock();
}
}
package cn.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* -
*
* @author
* @version 1.0 2013-7-26 04:13:45
*/
public class ThreadAtomicTest2 {
public static void main(String[] args) throws InterruptedException {
ExecutorService pool = Executors.newFixedThreadPool(2);
Lock lock = new ReentrantLock(false);
Runnable t1 = new AtomicRunnable2(" ", 2000, lock);
Runnable t2 = new AtomicRunnable2(" ", 3600, lock);
Runnable t3 = new AtomicRunnable2(" ", 2700, lock);
Runnable t4 = new AtomicRunnable2(" ", 600, lock);
Runnable t5 = new AtomicRunnable2(" ", 1300, lock);
Runnable t6 = new AtomicRunnable2(" ", 800, lock);
//
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
pool.execute(t6);
//
pool.shutdown();
}
}
3600, :13600
2700, :16300
600, :16900
1300, :18200
800, :19000
2000, :21000
ここでは、同時コードへのアクセスを制御するオブジェクトロックを使用します.何回実行しても、実行順序にかかわらず、最終残高は21000であり、この結果は正しい.原子量の使い方は簡単で,原子量の認識が鍵であり,原子は変数操作の原子性を保証するだけであるが,プログラム全体はスレッドの安全を考慮する必要がある.