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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值