尋找臨界區 :@slf4j
(topic =
"c.case1"
)public
class
case1
public
static
void
main
(string[
] args));
list.
add(t)
; t.
start()
;}//使得每個執行緒執行結束
list.
foreach
((t)
->
catch
(interruptedexception e)})
;//統計最終結果
log.
debug
("賣出去:"
+ sellcount.
stream()
.maptoint
(a->a)
.sum()
);log.
debug
("剩餘票數:"
+ ticketwindow.
getcount()
);}}
class
ticketwindow
public
intgetcount()
public
void
setcount
(int count)
//賣出去多少張表,如果返回0則表示沒賣出去票
public
intsell
(int amount)
else
}}
尋找共享變數int sell = ticketwindow.
sell
(getrandom()
);sellcount.
add(sell)
;
解決方法:
可以給共享變數上鎖,使用關鍵字synchronized
,可以將鎖加在sell方法上
等價於public
synchronized
intsell
(int amount)
else
}
public
intsell
(int amount)
else
}}
臨界區@slf4j
(topic =
"c.case2"
)public
class
case2
public
static
void
main
(string[
] args)
throws interruptedexception })
; thread t2 =
newthread((
)->})
;//分別啟動t1 t2
t1.start()
; t2.
start()
;//等待t1 t2跑完
t1.join()
; t2.
join()
; log.
debug
("賬戶a :"
+ a.
getmoney()
);log.
debug
("賬戶b :"
+ b.
getmoney()
);log.
debug
("total:{}"
,(a.
getmoney()
+b.getmoney()
));}
}class
account
public
intgetmoney()
public
void
setmoney
(int money)
public
void
transfer
(account target,
int amount)
}}
共享變數public
void
transfer
(account target,
int amount)
}}
與上乙個例子不同的是,該臨界區存在的共享變數有兩個,分別是this.money
和target.money
,所以如果在transfer上面加上鎖,還能不能鎖得住,能 不能解決執行緒安全問題呢?
並不能!public
synchronized
void
transfer
(account target,
int amount)
}
原因是:此時的synchronized只能鎖定住當前的物件的共享變數,也就是說誰呼叫transfer就會鎖住誰的money屬性,因此並不能解決執行緒安全問題,那麼該如果才能同時鎖住兩個物件呢?
解決方法:擴大鎖的範圍,從鎖住物件擴大至鎖住整個類,因為無論是this.money
和target.money
它們都屬於account類,因此可以修改臨界區的鎖範圍,如下:
此時便達到我們的執行緒安全目的。public
void
transfer
(account target,
int amount)
}}
兩個lock的經典使用示例
示例一 public class numberprintdemo catch interruptedexception e 當state 1時,輪到執行緒1列印5次數字 for int j 0 j 5 j system.out.println 執行緒1列印完成後,將state賦值為2,表示接下來將輪...
兩個經典的Oracle觸發器示例
案例一 題目 觸發器 新增員工資訊,流水號作為自動編號 通過序列生成 並且判斷如果工資小於0,則改為0 如果大於10000,則改為10000。create table emp2 e id number,e no number,e name varchar2 20 e sal number selec...
兩個經典的Oracle觸發器示例
from 案例一 題目 觸發器 新增員工資訊,流水號作為自動編號 通過序列生成 並且判斷如果工資小於0,則改為0 如果大於10000,則改為10000。create table emp2 e id number,e no number,e name varchar2 20 e sal number ...