使用多线程的经典条件:
1.原始类
2.对原始类使用Runnable 找出变化的条件
3.Thread t = new Thread(Runnable)
t.start();
解决同步问题:
ReentrantLock lock = new ReentrantLock();
code:
lock.lock();
try{
criticalSelection();
} finally{
lock.unLock();
}
这段代码使只有一个线程能够访问lock中间部分的代码
条件对象
当线程进入临界区,却发现要满足某一条件之后它才能执行。这时我们将使用await,signal,signalAll,方法来完成线程的条件访问。
Condition condition = lock.newCondition();
while(!(ok to proceed)){
condition.await();
}
change the condition
condition.signalAll();
总结:
锁用来保护代码片段,任何时刻只能有一个线程执行被保护的代码
锁可以管理试图进入被保护代码段的线程
锁可以拥有一个或多个相关的条件对象
每个条件对象管理那些已经进入被保护的代码段但还不能运行的线程
synchronized关键字:
public synchronized void method(){
}
等价于
public void method(){
this.instinctLock.lock();
try{
method body;
}
finally{
this.instinctLock.unLock();
}
条件对象:
public synchronized void method(){
while(!(process is ok)
wait();
metohd body;
notifyAll();
}
代码建议:
最好既不用Lock/Condition也不实用synchronized关键字,最好是使用java.util.concurrent包中的一种机制,它会处理所有的加锁。
如果synchronized关键字适合我们的程序尽量使用它,因为这个可以减少代码量,减少出错的几率
特别需要Lock/Condition结构提供的独有特性时,再用
同步阻塞
synchronized(obj){
critical section
}
public void transfer(Vector<Double> account, int from, int to, int amount){
synchronized(accounts)
accounts.set(from, accounts.get(from) - amount);
acounts.set(to, accounts.get(to) + amount);
}
sys
}
上述例子假定Vector的所有可修改方法都使用了内部锁。若假定成立,这个方法是可行的。
tryLock方法试图申请一个锁,在成功获得锁后返回true,否则,返回false
if(tryLock.tryLock()){
//now the thread owns the lock
try{. .}
finally{tryLock.unLock()}
} else
//do anything else.
可以对tryLock使用超时参数
读写锁:读锁可以被所有读者公用但会排斥所有写操作;写锁排斥其他写操作和读操作
1.构造一个ReentrantReadWriteLock 对象
private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
2.读取读锁和写锁
private Lock readLock = rwl.readLock();
private Lock writeLock = rwl.writeLock();
3.对所有的访问者加读锁
private double getTotalBalance(){
readLock.lock()
try{. . .}
finally{
readLock.unLock();
}
}
4.对所有的修改者加写锁
Volatile关键字
可以替代synchronized关键字对原始类性进行声明
锁测试或锁超时