同步-同步鎖-死鎖-線程交互-線程綜合示例
阿新 • • 發佈:2017-08-01
tco stc 指定 random sys args increase join spa
一、同步
1.作用:為了避免多個線程同時訪問並修改共享數據所導致的不安全問題。
2.使用synchronized(對象){}方式。
二、機制
1.當線程要進入某個被“同步鎖”鎖住代碼之前,線程必須先獲得“同步鎖對象”
2.保證任何時刻,只有一條線程能執行被鎖代碼
3.不許以“競爭資源”作為“同步對象”
三、同步鎖的釋放
1.代碼完成
2.語句塊拋出異常
3.語句塊遇到break,return
4.調用wait方法
5.註意:sleep和yield方法不會釋放同步鎖
四、對象鎖池
新建->start()->可運行<---調度任務--> 正在運行->run()完成->終止
正在運行---阻塞事件(sleep,join)----->阻塞-----解除阻塞---->可運行
正在運行---同步的------>阻塞對象的鎖池-----獲得所---->可運行
五、代碼演示
package 同步; public class Couner implements Runnable{ private int counter=200; public void run() { for(int i = 0;i<50;i++){ synchronized (this) { counter-=2; try {Thread.sleep(10);} catch (InterruptedException e) {} System.out.print(counter+" "); } } } }
package 同步; public class TestCounersyc { public static void main(String[] args) { Couner c = new Couner(); Thread t1= new Thread(c); Thread t2 = new Thread(c); t1.start(); t2.start(); } }
六、死鎖
1.定義:兩個線程都在等待對方執行完畢才能往下執行時發生死鎖,陷入無限等待中。
2.解決:指定獲取鎖的順序,並強制線程按照指定的順序獲取鎖。
3.死鎖代碼案例
package 死鎖; public class DeadLock { private final Object left = new Object(); private final Object right = new Object(); public void leftRight() throws Exception { synchronized (left) { Thread.sleep(2000); synchronized (right) { System.out.println("leftRight end!"); } } } public void rightLeft() throws Exception { synchronized (right) { Thread.sleep(2000); synchronized (left) { System.out.println("rightLeft end!"); } } } }
package 死鎖; public class Thread0 extends Thread { private DeadLock dl; public Thread0(DeadLock dl) { this.dl = dl; } public void run() { try { dl.leftRight(); } catch (Exception e) { e.printStackTrace(); } } }
package 死鎖; public class Thread1 extends Thread { private DeadLock dl; public Thread1(DeadLock dl) { this.dl = dl; } public void run() { try { dl.rightLeft(); } catch (Exception e) { e.printStackTrace(); } } }
package 死鎖; public class Test { public static void main(String[] args) { DeadLock dl = new DeadLock(); Thread0 t0 = new Thread0(dl); Thread1 t1 = new Thread1(dl); t0.start(); t1.start(); while(true); } }
七、線程交互
1.wait方法使線程進入阻塞狀態,直到線程得到喚醒通知,或者達到指定時間。
註意:
1)wait和notify方法僅能在所訪問對象的同步塊內調用。
2)當線程調用wait方法進入等待狀態時,會釋放對象鎖標記。
2.喚醒方式
通知喚醒-notify或notifyAll方法
主動喚醒-到達阻塞事件
中斷喚醒-被另一個線程調用interrupt方法,收到InterruptedException異常。
3.代碼演示
package 線程交互; public class Couner implements Runnable{ private int counter=0; public void setCounter(int counter){ this.counter = counter; } public synchronized void run() { if(counter<100){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } counter-=100; System.out.println("counter = " + counter); System.out.println("Counter線程結束"); } }
package 線程交互; public class TestCounerWait { public static void main(String[] args) { Couner c = new Couner(); Thread t = new Thread(c); t.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { } synchronized (c) { c.setCounter(150); c.notify(); } System.out.println("main線程結束"); } }
八、線程綜合示例(代碼)
package 線程綜合示例; public class Couner{ private int counter=0; public synchronized int increase(int n){ counter+=n; this.notify(); System.out.printf("生產:couner=%-2d n=%-2d\n",counter,n); return counter; } public synchronized int decrease(int n){ while(counter<n){ try { this.wait(); } catch (InterruptedException e) { } } counter-=n; System.out.printf("消費:couner=%-2d n=%-2d\n",counter,n); return counter; } }
package 線程綜合示例; public class Producer implements Runnable{ private Couner couner; public Producer(Couner couner){ this.couner = couner; } public void run() { for(int i=0;i<50;i++){ couner.increase((int)(Math.random()*10)); try { Thread.sleep((int)(Math.random()*100)); } catch (InterruptedException e) { e.printStackTrace(); } } } }
package 線程綜合示例; public class Consumer implements Runnable{ private Couner couner; public Consumer(Couner couner){ this.couner = couner; } public void run() { for(int i=0;i<50;i++){ couner.decrease((int)(Math.random()*8)); try { Thread.sleep((int)(Math.random()*100)); } catch (InterruptedException e) { e.printStackTrace(); } } } }
package 線程綜合示例; public class TestPC { public static void main(String[] args) { Couner couner = new Couner(); Producer p = new Producer(couner); Thread t1 = new Thread(p); Consumer c = new Consumer(couner); Thread t2 = new Thread(c); t1.start(); t2.start(); } }
同步-同步鎖-死鎖-線程交互-線程綜合示例