JDK中Thread.State類的幾種狀態
執行緒的生命週期
執行緒的安全問題(同步與互斥)
方法一:同步程式碼塊
多個執行緒的同步監視器(鎖)必須的是同一把,任何一個類的物件都可以
synchronized(同步監視器){
} //說明:操作共享資料的程式碼,即為需要被同步的程式碼(對共享資料的操作)
對於Thread實現和Runnable實現,同步鎖需要區別
1.Thread下的同同步鎖
class WinThread extends Thread{
/*
方式一 繼承Thread
*/
private static int ticket=100; //需要設定靜態變數
private static Object ticketLock=new Object(); //同步監視器,靜態,因為要是共享唯一變數
@Override
public void run() {
while(true)
{
synchronized (ticketLock){
if (ticket > 0)
{
System.out.println(this.getName() + "賣票: " + ticket);
ticket--;
}
else break;
}
}
}
}
2.Runnable下的同步鎖
class winRunnable implements Runnable{
private int ticket=100; //不用設定成靜態變數
private Object obj=new Object(); //宣告一個物件為鎖
@Override
public void run() {
while(true)
{
try {
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(obj){ //互斥操作
if (ticket > 0)
{
System.out.println(Thread.currentThread().getName() + "賣票: " + ticket);
ticket--;
}
else break;
}
}
}
}
Thread下可以考慮用WinThread.class當鎖,而Runnable下可以考慮用this當鎖(總之要分析是不是同一個鎖)
自己的坑:不能把共享的資料當作鎖(例如WinThread下的int ticket改成Integer後當鎖),這裡還是會有問題
方法二:同步方法(程式碼略)
多宣告一個對共享資料資料操作的方法,在方法的前面新增宣告synchronized,而不是直接在run()前面加
1.同步方法中也涉及到同步鎖,但鎖是預設的
2.非靜態的同步方法,鎖是this
靜態的同步方法,鎖是當前類本身——xxx.class
* 同步方法synchronized實現runnable介面
* private synchronized void 方法(){//普通同步方法的同步監視器是this
* //需要互斥的程式碼
* }
* 同步方法synchronized實現繼承Thread類
* 因為不同執行緒是Thread類的不同物件,所以一般要用靜態
* private static synchronized void 方法(){//靜態同步方法預設同步監視器是類本身
* //需要互斥的程式碼
* }
同步的侷限性:操作同步程式碼時,只能有一個執行緒參與,其他執行緒等待,相當於互斥量為1
單例模式的同步問題
死鎖問題
方法二:Lock(鎖) ---JDK5.0新增
class LockRunnable implements Runnable{
private int ticket=100; //不用設定成靜態變數
private ReentrantLock lock=new ReentrantLock(true); //true為選擇FIFO的公平
@Override
public void run() {
while(true)
{
try {
try {
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.lock();
if (ticket > 0)
{
System.out.println(Thread.currentThread().getName() + "賣票: " + ticket);
ticket--;
}
else break;
}finally {
lock.unlock();
}
}
}
}
面試題:synchronized 與 Lock 的區別
相同:二者都可以解決執行緒安全問題
不同:synchronized機制在執行完相應的同步程式碼之後,自動的釋放同步監視器
Lock需要手動的啟動同步 .lock() ,同時結束同步也需要手動 .unlock()