java中當多個現成同時操縱同一資源的時候需要考慮同步的問題。如車站售票,不同售票點賣同一班次車票的時候就要同步,否則賣票會有問題。下面代碼模擬車站賣票:
class TicketSeller implements Runnable { public int ticket = 20; public void run() { for(int i = 0; i < 100; i++) { synchronized(this) { if(this.ticket-- >0) { Utilities.sleep(300); System.out.println(Thread.currentThread().getName() + "賣出一張票,余票:" + (this.ticket) + "張"); } } } } } class Utilities { public static void sleep(int timeSpan) { try { Thread.sleep(timeSpan); } catch (Exception e) { } } } class Hello { public static void main(String[] args) { TicketSeller ts = new TicketSeller(); Thread tl = new Thread(ts,"銅梁站"); Thread bs = new Thread(ts,"璧山站"); Thread spb = new Thread(ts,"沙坪壩站"); tl.start(); bs.start(); spb.start(); } }
輸出結果:
但有時過多的使用同步會造成程序性能下降。除此之外過多同步還會發生更嚴重的后果:死鎖。
也就是說,同步代碼塊中都去爭奪同一資源,互不相讓。舉個例子,在一條東西方向的狹窄的巷道中,AB兩車相遇,互補退讓,結果是兩個車都走不了,這就是死鎖。這里隱含了一個情景就是,A車占有東邊這一段道路,它需要B車讓出B車占有西邊的道路,而同時B車占有西邊的道路,它需要A車讓出A車所占有的西邊的道路。兩車各自占有各自的資源,且同時爭奪對方占有的資源,互補相讓,就造成了死鎖。
這里,為了更好的闡述並模擬JAVA中死鎖的情況。我再舉一個例子:
小紅和小明馬上就要畢業了,都在准備畢業論文的撰寫。他們的論文都要用到兩本書,一本是《匯編語言》,另一本是《算法導論》。他們都要去圖書館借閱這兩本書,但圖書館規定某一人一次只能借閱1本書。於是小紅借了《匯編原理》,小明借了《算法導論》。過了一段時間后,他們論文都完成了一 半。此時,小紅需要小明手中的《算法導論》,同時小明也要小紅手中的《匯編原理》。但是小紅對小明說:“你先把《算法導論》給我了,我完成論文后就把《匯編原理》給你。” 小明不同意,他對小紅說:“你把《匯編原理》先給我,我完成論文后把《算法導論》給你。” 這樣,小紅和小明各持有一本書,卻又要求獲得對方的書才交出自己持有的那本書。他們兩人互不相讓,結果就導致了死鎖的發生。
現在我用JAVA語言對以上場景進行模擬:
class Book { public String name; public float price; public Book(String name, float price) { this.name = name; this.price = price; } } class Student implements Runnable { private String studentName; private Book book1; private Book book2; public Student(String studentName,Book book1, Book book2) { this.book1 = book1; this.book2 = book2; this.studentName = studentName; } public void run() { synchronized(this.book1) { System.out.println(this.studentName+"拿到了"+this.book1.name +"開始寫論文"); Utilities.sleep(5000); System.out.println(this.studentName+"完成一半需要"+this.book2.name); synchronized(this.book2) { System.out.println(this.studentName+"拿到了"+this.book2.name +"繼續寫論文"); } System.out.println(this.studentName+"完成了論文"); } } } class Utilities { public static void sleep(int timeSpan) { try { Thread.sleep(timeSpan); } catch (Exception e) { System.out.println(e); } } } class Hello { public static void main(String[] args) { Book book1 = new Book("匯編原理",23.5f); Book book2 = new Book("算法導論",85.5f); Thread xh = new Thread(new Student("小紅",book1,book2)); Thread xm = new Thread(new Student("小明",book2,book1)); xh.start(); xm.start(); } }
輸出結果:
上圖顯示,程序一直卡在這個地方,不會往下執行。這就是死鎖。