Java笔记整理 —— Synchronized、锁

Synchronized

线程同步机制简介

可以理解为某人进厕所后把门关上(上锁),然后出来的时候剩下的人才能进去。 

售票问题的解决

class AA implements Runnable{
    public static int TicketNums = 100; //共享票数
    private boolean loop = true;
    public synchronized void sell(){ 
//把售票设为一个同步方法,这样每次只有一个线程访问
        if(TicketNums <=0){
            System.out.println("售票结束");
            loop = false; 
            return;
        }
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        TicketNums--; //
        System.out.println("窗口 " + Thread.currentThread().getName() + "售出一张票"
         + " 剩余票数:" + TicketNums);
    }
    @Override
    public void run() {
        while(loop){ //持续贩卖
            sell();
        }
    }
}
    public static void main(String[] args) throws InterruptedException {
        AA aa = new AA();
        new Thread(aa).start(); 
        new Thread(aa).start();
        new Thread(aa).start(); //一个对象创造三个线程
}

互斥锁

    当一个方法设为synchronized,就相当于加了一把锁(如果锁在对象上那就是对象锁),t1,t2,t3会争夺这把锁。

当一个线程争夺到时,锁会被打开,然后执行方法。

当方法执行完毕后,继续锁上,然后线程继续争抢。 

 public synchronized void sell() {}  就是一个同步方法,此时锁在this对象上。 

 当然也可以在代码块上写synchronize,同步代码块,互斥锁还是this对象。

 public void sell(){ 
    synchronized(this){  //同步代码块
        if(TicketNums <=0){
            System.out.println("售票结束");
            loop = false; 
            return;
        }
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        TicketNums--; //
        System.out.println("窗口 " + Thread.currentThread().getName() + "售出一张票"
         + " 剩余票数:" + TicketNums);
    }
        
 }

5. 非静态同步方法的锁可以是当前对象,也可以是其它对象(要求是同一个对象,比如Object)。 

    Object object = new Object();
    AA aa = new AA();
    BB bb = new BB();
    public void sell(){
        synchronized (object){ //只有object可以,父类(bb)和自己(aa)都不行 
                               //多个线程访问同一个对象
            if(TicketNums <=0){
                System.out.println("售票结束");
                loop = false;
                return;
            }
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            TicketNums--;
            System.out.println("窗口 " + Thread.currentThread().getName() + 
               "售出一张票"  + " 剩余票数:" + TicketNums);
        }
    }

6. 静态的同步方法的锁为当前类本身。

    public static void m2(){
        synchronized (Test.class){ //不能写this了,要写 当前类名.class
            System.out.println("静态方法中的同步代码块");
        }
    }

 有一个重点要说明的: 多个线程的锁对象应为同一个

synchronized (this){...} //同步代码块
public synchronized void sell(){...} //同步方法

    对于以上两种同步写法,所使用的对象都是this(也就是给this加了把锁),这样的写法对下面的主函数是有用的: 因为它们对应的都是一个对象,对应的方法也是同一个。

        AA aa = new AA();
        new Thread(aa).start(); 
        new Thread(aa).start();
        new Thread(aa).start(); //一个对象创造三个线程

  但是对于下面这种写法就不管用了:

        AA aa1 = new AA();
        AA aa2 = new AA();
        AA aa3 = new AA();
        new Thread(aa1).start();
        new Thread(aa2).start();
        new Thread(aa3).start();

   这里创建了三个不同的对象,因此它们的锁各管各的,相当于有三把锁,每个线程每次都能抢到锁。因此就不管用了。

线程死锁

比如: 妈妈:你先完成作业,才让你玩手机。  小明:你先让我玩手机,我才完成作业。

释放锁 

释放锁:从 线程调度器中出来(线程状态图的绿色块)就释放了锁,如果没有出来就是没有释放

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值