保證線程安全的三種方式
(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();
}
}
}