1. 程式人生 > >同步-同步鎖-死鎖-線程交互-線程綜合示例

同步-同步鎖-死鎖-線程交互-線程綜合示例

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();
    }
}

同步-同步鎖-死鎖-線程交互-線程綜合示例