java同步鎖(synchronized)鎖方法還是鎖類??

首先引入gitHub上面一個解釋

一.原理分析

1. 同步一個代碼塊

public void func() {
    synchronized (this) {
        // ...
    }
}

它只作用於同一個對象,如果調用兩個對象上的同步代碼塊,就不會進行同步。

2. 同步一個方法

public synchronized void func () {
    // ...
}

它和同步代碼塊一樣,作用於同一個對象。

3. 同步一個類

public void func() {
    synchronized (SynchronizedExample.class) {
        // ...
    }
}

作用於整個類,也就是說兩個線程調用同一個類的不同對象上的這種同步語句,也會進行同步
另外我覺得這裏面不只是鎖類單一的,只要是常量不變的即可,是爲了鎖唯一,也就是一個線程進去之後,獲得了這把鎖,因爲這把鎖唯一,那麼只有這個線程裏面所有的東西都執行完畢,纔會下一個線程進入
4.同步靜態方法

public synchronized static void fun() {
    // ...
}

二.DEMO

public class Ticket {

    public static void main(String[] args) {

        GetTicket getTicket=new GetTicket();
        Thread thread1=new Thread(getTicket,"我");
        Thread thread2=new Thread(getTicket,"張");
        Thread thread3=new Thread(getTicket,"黃牛");

        thread1.start();
        thread2.start();
        thread3.start();
    }
}
class GetTicket implements Runnable{

    private  int ticketNum=10;
    boolean flag=true;
    @Override
    public void run() {
        while(flag){
            buy();
        }
    }

    //synchronized 同步方法 鎖的是this
    private synchronized  void buy(){
        if(ticketNum<=0){
            flag=false;
            return ;
        }
        //模擬延時
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName()+"取到了"+ticketNum--);
    }
}

在這裏插入圖片描述
這裏可以看到只新建了一個對象,也就是隻有一份資源,三個代理去搶,所以鎖方法即可。

如果改成不同的對象,那麼這個鎖就失去意義了,相當於兩份資源,如果還是鎖的方法,就不是同步了

public class Ticket {

    public static void main(String[] args) {

        GetTicket getTicket=new GetTicket();
        GetTicket getTicket2=new GetTicket();
        Thread thread1=new Thread(getTicket,"我");
        Thread thread2=new Thread(getTicket2,"張");


        thread1.start();
        thread2.start();
      
    }
}
class GetTicket implements Runnable{

    private  int ticketNum=10;
    boolean flag=true;
    @Override
    public void run() {
        while(flag){
            buy();
        }
    }

    //synchronized 同步方法 鎖的是this
    private synchronized void buy(){
        if(ticketNum<=0){
            flag=false;
            return ;
        }
        //模擬延時
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName()+"取到了"+ticketNum--);
    }
}

在這裏插入圖片描述
這個時候只有synchronized(this)纔可以。

再來看一個例子

public class UnsafeBank {
    public static void main(String[] args) {
        Account account = new Account(500,"結婚基金");
        Drwaing you=new Drwaing(account,50,"你");
        Drwaing wife=new Drwaing(account,100,"妻子");
        you.start();
        wife.start();
    }
}
class Account{
    int money;//餘額
    String name;//卡名

    public Account(int money, String name) {
        this.money = money;
        this.name = name;
    }
}
class Drwaing extends Thread{
    Account account;
    int drawingMoney;
    int nowMoney;

    public Drwaing(Account account,int drawingMoney,String name){
       super(name);
        this.account=account;
        this.drawingMoney=drawingMoney;

    }

    @Override
//如果在方法上面加鎖,那麼鎖的就是這個銀行this,但實際上我們操作的是account對象
    public  void run() {
        synchronized (UnsafeBank.class) {
            if (account.money - drawingMoney < 0) {
                System.out.println(Thread.currentThread().getName() + "錢不夠");
                return;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            account.money = account.money - drawingMoney;
            nowMoney = nowMoney + drawingMoney;
            System.out.println(account.name + "餘額" + account.money);
            System.out.println(this.getName() + "手裏的錢" + nowMoney);
        }
    }
}

在這裏插入圖片描述
這個因爲對象是兩個,如果鎖的是方法,那麼就不安全了
在這裏插入圖片描述
參考GitHUb

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章