最近,正学习java线程,总结如下:
java.util.concurrent.locks.Lock
void lock() 获得这个锁,如果这个锁当前被另一个线程所持有,则该线程发生阻塞。
void unlock() 释放锁定。
java.util.concurrent.locks.ReentrantLock
public ReentrantLock() 创建一个可被用来保护临界区的可重人锁。
用ReentrantLock保护代码块的基本结构如下:
myLock.lock(); // ReentrantLock对象
try
{
// 临界区
}
finally
{
myLock.unlock(); // 确保锁能够释放
}
该结构保证在任何时刻只有一个线程能够进入临界区。一旦一个线程锁住了锁对象,其他任何线程都无法通过lock语句。当其他线程调用lock时,它们会被阻塞,直到第一线程释放锁对象。
使用Lock和Condition对象的关键点:
1.锁用来保护代码片段,任何时刻只允许一个线程执行被保护的代码。
2.锁可以管理试图进入被保护代码段的线程。
3.锁可以拥有一个或多个相关的条件对象。
4.每个条件对象管理那些已进入被保护代码段但还不能运行的线程。
Condition有两个方法可以唤醒等待线程:signalAll()方法和signal()方法。
signalAll()方法唤醒所有等待线程,该方法不会立即激活等待线程,它只是解除等待线程的阻塞状态,这样这些线程就可以在当前线程退出同步方法后,通过竞争获得对对象的访问。
而signal()方法则是随机解除等待集中某个线程的阻塞状态。该方法存在一定的危险,如果被随机选中的线程发现自己还是无法运行,它会再次被阻塞。如果没有任何其他线程再次调用singal()方法,那么系统就死锁了。
当一个线程调用await()方法时,它无法自己解除阻塞状态。它把自己的命运交给了其他线程。如果没有任何其他线程来解除等待线程的阻塞状态,它就永远也不会运行了,这会导致死锁。
public class TestSync implements Runnable {
Timer timer = new Timer();
public static void main(String[] args)
{
TestSync test = new TestSync();
Thread t1 = new Thread(test);
Thread t2 = new Thread(test);
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}
public void run() {
timer.add(Thread.currentThread().getName());
}
}
class Timer {
private static int num = 0;
public /*synchronized*/ void add(String name) {
synchronized (this) {
num++;
try {
Thread.sleep(1);
}
catch (InterruptedException e)
{
}
System.out.println(name + ", 你是第" + num + "个使用timer的线程");
}
}
}
import java.util.concurrent.locks.*;
/**
* This program shows how multiple threads can safely access a data structure.
*/
public class SynchBankTest
{
public static void main(String[] args)
{
Bank b = new Bank(NACCOUNTS, INITIAL_BALANCE);
int i;
for (i = 0; i < NACCOUNTS; i++)
{
TransferRunnable r = new TransferRunnable(b, i, INITIAL_BALANCE);
Thread t = new Thread(r);
t.start();
}
}
public static final int NACCOUNTS = 100;
public static final double INITIAL_BALANCE = 1000;
}
/**
* A bank with a number of bank accounts.
*/
class Bank
{
/**
* Constructs the bank.
* @param n the number of accounts
* @param initialBalance the initial balance
* for each account
*/
public Bank(int n, double initialBalance)
{
accounts = new double[n];
for (int i = 0; i < accounts.length; i++)
accounts[i] = initialBalance;
bankLock = new ReentrantLock();
sufficientFunds = bankLock.newCondition();
}
/**
* Transfers money from one accounts to another.
* @param from the account to transfer from
* @param to the account to transfer to
* @param amount the amount to transfer
*/
public void transfer(int from, int to, double amount)
throws InterruptedException
{
bankLock.lock();
try
{
while (accounts[from] < amount)
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());
sufficientFunds.signalAll();
}
finally
{
bankLock.unlock();
}
}
/**
* Gets the sum of all account balances.
* @return the total balance
*/
public double getTotalBalance()
{
bankLock.lock();
try
{
double sum = 0;
for (double a : accounts)
sum += a;
return sum;
}
finally
{
bankLock.unlock();
}
}
/**
* Gets the number of accounts in the bank.
* @return the number of accounts
*/
public int size()
{
return accounts.length;
}
private final double[] accounts;
private Lock bankLock;
private Condition sufficientFunds;
}
/**
* A runnable that transfers money from an account to other
* accounts in a bank.
*/
class TransferRunnable implements Runnable
{
/**
* Constructs a transfer runnable.
* @param b the bank between whose account money is transferred
* @param from the account to transfer money from
* @pram max the maximum amount of money in each transfer
*/
public TransferRunnable(Bank b, int from, double max)
{
bank = b;
fromAccount = from;
maxAmount = max;
}
public void run()
{
try
{
while (true)
{
int toAccount = (int) (bank.size() * Math.random());
double amount = maxAmount * Math.random();
bank.transfer(fromAccount, toAccount, amount);
Thread.sleep((int) (DELAY * Math.random()));
}
}
catch (InterruptedException e) {}
}
private Bank bank;
private int fromAccount;
private double maxAmount;
private int repetitions;
private int DELAY = 10;
}