Thread -- Lock Objects and Condition Objects

Lock Objects :

The basic outline for protecting  a code block with a "ReentrantLock" is :

myLock.lock();    //a ReentrantLock object
try {
    critical section
} finally {
    myLock.unlock();    //make sure the lock is unlocked even if an exception is throw
}

For Example:  (this code snippet references the simple program located at the bottom of this article)

package ConcurrentTest;

import java.util.Arrays;

/**
 * Created by lenovo on 2018/6/13.
 */
public class Bank {
    private final double[] accounts;
    private final Lock bankLock = new ReentrantLock();    //ReentrantLock implements the lock interface

    public Bank(int n, double initialBalance) {
        accounts = new double[n];
        Arrays.fill(accounts, initialBalance);
    }

    public void transfer(int from, int to, double amount) {
        bankLock.lock();    //the first thread that access this block will acquire the lock, 
                            //the others will wait this thread relinquishing the lock

        try {

            if (accounts[from] < amount) {
                return;
            }

            System.out.print(Thread.currentThread());
            accounts[from] -= amount;
            System.out.printf(" %10.2f from %d to %d", amount, from, to);
            accounts[to] += amount;
            System.out.printf(" Total Balance: %10.2f\n", getTotalBalance());
        } finally {
            bankLock.unlock();  //when the thread finishes, make sure to relinquish the lock 
                                //so that one of other threads can acquire the lock
        }
    }

    private double getTotalBalance() {
        double sum = 0;

        for(double account : accounts) {
            sum += account;
        }

        return sum;
    }

    public int size() {
        return accounts.length;
    }

}


Condition Objects :

A lock object can have one or more associated condition objects. You obtain a condition object with the "newCondition" method on the associating lock object. It is customary to give each condition object a name that evokes the condition that it represents. (with doing so, whenever we see the condition object, we will recogonize the meaning the condition represents). 

For example, consider the following code logic:  (this code snippet references the simple program located at the bottom of this article)

//The following code logic represents that the current thread will keeping deactivated 
//unless the account balance is sufficent to transfer.
Condition sufficientFunds = bankLock.newCondition();    //the condition object name should be meaningful.
                                                        //in this case, it represents that the accounts[from] must be
                                                        //sufficient for covering the amount to transfer
... ...
... ...
while (accounts[from] < amount) {
    sufficientFunds.await();    //after executing this method, the thread
                                //blocks, relinquishes the lock, and
                                //enters the awaiting set of the condition
}

With call the "await" method on the condition object (in this case it is "sufficientFunds"), the current thread blocks, and relinquishes the lock. When another thread access the critical code block, and call the "signalAll" method on the same condition object (in this case the condition object is "sufficientFunds"), all deactivated threads by the call to the "await" method are changed to be runnable, queue up to acquire the lock, and the scheduler will eventually activate them again.



The simple program simulates funds transfering from one account to another in a bank. We simulated an array of accounts transfering funds to each other randomly.

package ConcurrentTest;

import java.util.Arrays;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by lenovo on 2018/6/13.
 */
public class Bank {
    private final double[] accounts;
    private Lock bankLock = new ReentrantLock();
    private Condition sufficientFunds = bankLock.newCondition();

    public Bank(int n, double initialBalance) {
        accounts = new double[n];
        Arrays.fill(accounts, initialBalance);
    }

    public void transfer(int from, int to, double amount) {
        bankLock.lock();

        try {

            while (accounts[from] < amount) {
                sufficientFunds.signal();
                sufficientFunds.await();
            }

            System.out.print(Thread.currentThread());
            accounts[from] -= amount;
            System.out.printf(" %10.2f from %d to %d", amount, from, to);
            accounts[to] += amount;
            System.out.printf(" Total Balance: %10.2f\n", getTotalBalance());
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            sufficientFunds.signalAll();
        } finally {
            sufficientFunds.signal();
            bankLock.unlock();
        }

    }

    private double getTotalBalance() {
        double sum = 0;

        for(double account : accounts) {
            sum += account;
        }

        return sum;
    }

    public int size() {
        return accounts.length;
    }

}
package ConcurrentTest;

/**
 * Created by lenovo on 2018/6/13.
 */
public class SynchBankTest {
    public static final int NACCOUNTS = 100;
    public static final double INITIAL_BALANCE = 1000;
    public static final double MAX_AMOUNT = 1000;
    public static final int DELAY = 10;

    public static void main(String[] args) {
        Bank bank = new Bank(NACCOUNTS, INITIAL_BALANCE);

        for (int i = 0; i < bank.size(); i++) {
            int fromAccount = i;

            Runnable r = () -> {
                try {
                    while (true) {
                        int toAccount = (int) (bank.size() * Math.random());
                        double amount = MAX_AMOUNT * Math.random();
                        bank.transfer(fromAccount, toAccount, amount);
                        Thread.sleep((int) (DELAY * Math.random()));
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            };

            new Thread(r).start();
        }

    }

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值