げんしへんすう
4722 ワード
このようなエラーを回避するために,Javaは原子変数を導入した.1つのスレッドが原子変数に対して動作している場合、他のスレッドも同じ原子変数に対して動作を実行しようとする場合、変数の実装クラスは、動作が1ステップ以内に完了するかどうかを調べるメカニズムを提供します.一般的に、この操作はまず変数値を取得し、その後、変数の値をローカルに変更しますが、この変数の値で置き換えようとする前の値です.以前の値が他のスレッドに変更されていない場合は、この置換操作を実行できます.そうでなければ、メソッドはこの操作を実行します.この操作はCAS原子操作となる.
原子変数は、ロックまたは他の同期メカニズムを使用して値への同時アクセスを保護しません.操作はCAS原子に基づいて操作される.彼はマルチスレッドが同じ時間に1つの原子を動作させることを保証し,データの不一致の誤りを生じず,同期機構を用いて保護された通常の変数よりも性能が優れている.
Code
原子変数は、ロックまたは他の同期メカニズムを使用して値への同時アクセスを保護しません.操作はCAS原子に基づいて操作される.彼はマルチスレッドが同じ時間に1つの原子を動作させることを保証し,データの不一致の誤りを生じず,同期機構を用いて保護された通常の変数よりも性能が優れている.
Code
package com.packtpub.java7.concurrency.chapter6.recipe08.task;
import java.util.concurrent.atomic.AtomicLong;
/**
* This class simulate a bank account
*
*/
public class Account {
/**
* Balance of the bank account
*/
private AtomicLong balance;
public Account(){
balance=new AtomicLong();
}
/**
* Returns the balance of the account
* @return the balance of the account
*/
public long getBalance() {
return balance.get();
}
/**
* Establish the balance of the account
* @param balance the new balance of the account
*/
public void setBalance(long balance) {
this.balance.set(balance);
}
/**
* Add an import to the balance of the account
* @param amount import to add to the balance
*/
public void addAmount(long amount) {
this.balance.getAndAdd(amount);
}
/**
* Subtract an import to the balance of the account
* @param amount import to subtract to the balance
*/
public void subtractAmount(long amount) {
this.balance.getAndAdd(-amount);
}
}
package com.packtpub.java7.concurrency.chapter6.recipe08.task;
/**
* This class simulates a company that pays a salary an
* insert money into an account
*
*/
public class Company implements Runnable {
/**
* The account affected by the operations
*/
private Account account;
/**
* Constructor of the class. Initializes the account
* @param account the account affected by the operations
*/
public Company(Account account) {
this.account=account;
}
/**
* Core method of the Runnable
*/
@Override
public void run() {
for (int i=0; i<10; i++){
account.addAmount(1000);
}
}
}
package com.packtpub.java7.concurrency.chapter6.recipe08.task;
/**
* This class simulates a bank or a cash dispenser that takes money
* from an account
*
*/
public class Bank implements Runnable {
/**
* The account affected by the operations
*/
private Account account;
/**
* Constructor of the class. Initializes the account
* @param account The account affected by the operations
*/
public Bank(Account account) {
this.account=account;
}
/**
* Core method of the Runnable
*/
@Override
public void run() {
for (int i=0; i<10; i++){
account.subtractAmount(1000);
}
}
}
package com.packtpub.java7.concurrency.chapter6.recipe08.core;
import com.packtpub.java7.concurrency.chapter6.recipe08.task.Account;
import com.packtpub.java7.concurrency.chapter6.recipe08.task.Bank;
import com.packtpub.java7.concurrency.chapter6.recipe08.task.Company;
/**
* Main class of the example. It creates an account, a company and a bank
* to work with the account. The final balance should be equal to the initial, but....
*
*/
public class Main {
/**
* Main method of the example
* @param args
*/
public static void main(String[] args) {
// Creates a new account ...
Account account=new Account();
// an initialize its balance to 1000
account.setBalance(1000);
// Creates a new Company and a Thread to run its task
Company company=new Company(account);
Thread companyThread=new Thread(company);
// Creates a new Bank and a Thread to run its task
Bank bank=new Bank(account);
Thread bankThread=new Thread(bank);
// Prints the initial balance
System.out.printf("Account : Initial Balance: %d
",account.getBalance());
// Starts the Threads
companyThread.start();
bankThread.start();
try {
// Wait for the finalization of the Threads
companyThread.join();
bankThread.join();
// Print the final balance
System.out.printf("Account : Final Balance: %d
",account.getBalance());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}