保证线程安全的三种方式
(1)同步代码块:synchronized (obj),锁的必须是各线程共享的对象;
(2)同步方法: synchronized 方法,对自己加锁 ==synchronized (this)
(3)同步锁: (只介绍可重入锁)
final ReentrantLock lock=new ReentrantLock();
加锁:调用lock()方法;释放: 调用unlock()方法;
public void drawmoney(double num)
{//同步代码块;
<span style="white-space:pre"> </span>synchronized(obj){
if(num<getBalance())
{
System.out.println(Thread.currentThread().getName()+" succeed!");
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
setBalance(getBalance()-num);
System.out.println(Thread.currentThread().getName()+" your balance is:"+getBalance());
}
else
{
System.out.println(Thread.currentThread().getName()+" sorry,your balance is insufficient!");
System.out.println(Thread.currentThread().getName()+" your balance is:"+getBalance());
}
<span style="white-space:pre"> </span> }//自动解锁
}
//同步方法
public synchronized void drawmoney(double num)
{
if(num<getBalance())
{
System.out.println(Thread.currentThread().getName()+" succeed!");
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
setBalance(getBalance()-num);
System.out.println(Thread.currentThread().getName()+" your balance is:"+getBalance());
}
else
{
System.out.println(Thread.currentThread().getName()+" sorry,your balance is insufficient!");
System.out.println(Thread.currentThread().getName()+" your balance is:"+getBalance());
}
}//自动解锁
同步代码块和同步方法释放同步监视器条件:
(1)当前线程同步代码块或同步方法执行结束;
(2)当前线程在同步代码块或同步方法中执行了break、return等语句终止了该同步代码块或同步方法的继续执行;
(3)当前线程在同步代码块或同步方法中遇到未处理的error,exception导致该同步代码块或同步方法异常结束;
(4)当前线程在同步代码块或同步方法执行过程中,程序执行了同步监视器对象的wait()方法,则当前线程暂停,释 放同步监视器;
总而言之:同步代码块或同步方法执行结束或暂停,则释放同步监视器!
注意:在同步代码块或同步方法中执行sleep方法不会释放同步监视器
sleep方法、wait方法会阻塞线程,但wait方法会释放同步监视器
sleep到时间自动苏醒,wait需要被唤醒;
yield是线程让步,不会阻塞线程,从线程队列中选取优先级最高线程
//同步锁
public boolean transCount(Account de,double num)
{ //加锁
lock.lock();
try{
if(drawmoney(num))
{
de.deposit(num);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("转账成功!");
System.out.println("转账:"+de.getBalance());
return true;
}
else
{
System.out.println("转账失败!");
return false;
}
}finally
{ <span style="white-space:pre"> </span> //释放
lock.unlock();
}
}
public void deposit(double num)
{
lock.lock();
try{
setBalance(getBalance()+num);
}finally{
lock.unlock();
}
}
}