我们一起来回顾一下Synchronized关键字吧

多线程一直Java开发中的难点,也是面试中的常客,趁着还有时间,打算巩固一下JUC方面知识,我想机会随处可见,但始终都是留给有准备的人的,希望我们都能加油!!!

沉下去,再浮上来,我想我们会变的不一样的。

讲Lock接口之前先让我们一起来回顾一下Synchronized关键字吧。我想我们学Java开发这么久,不可能还有那个小伙伴没有用过synchronized

封面是庞大的朋友圈贡献的

JUC系列:

1、你知道什么是JUC了吗?

正在持续更新中...

一、synchronized 作用范围:

synchronized 是 Java 中的关键字,是一种同步锁。它修饰的对象有以下几种:

  1. 修饰某一处代码块,被修饰的代码块称为同步语句块。作用范围就是{}之间。作用的对象是调用这个代码块的对象。

    synchronized (this){
    	System.out.println("同步代码块 ");
    }
    
  2. 修饰在方法上,被修饰的方法就称为同步方法。作用范围则是整个方法。作用的对象则是调用这个方法的对象。

    public synchronized void sale() {
        
    }
    

    :1)synchronized 关键字不能被继承,如果父类中某方法使用了synchronized 关键字,字类又正巧覆盖了,此时,字类默认情况下是不同步的,必须显示的在子类的方法上加上才可。当然,如果在字类中调用父类中的同步方法,这样虽然字类并没有同步方法,但子类调用父类的同步方法,子类方法也相当同步了。

  3. . 修饰某个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象

        public static synchronized void test(){
            
        }
    
  4. 修饰某个类,其作用的范围是 synchronized 后面括号括起来的部分,作用的对象是这个类的所有对象

    class Ticket {
        public void sale() {
            synchronized (Ticket.class) {
    
            }
        }
    }
    

二、案例:

最后:我们拿synchronized 写一下多线程中的卖票的经典案例:

public class SynchronizedDemo {
    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        
        new Thread(() -> {
            for (int i = 0; i < 40; i++) {
                ticket.sale();
            }
        }, "A").start();

        new Thread(() -> {
            for (int i = 0; i < 40; i++) {
                ticket.sale();
            }
        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 40; i++) {
                ticket.sale();
            }
        }, "C").start();
    }
}

class Ticket {
    //票数
    private int number = 30;

    //操作方法:卖票
    public synchronized void sale() {
        //判断:是否有票
        if (number > 0) {
            System.out.println(Thread.currentThread().getName() + " : " + (number--) + " " + number);
        }
    }
}

三、总结:

synchronized 的同步效率非常低,因为一个如果某一块代码被synchronized 修饰了,当某一个线程进入了synchronized 修饰的代码块,那么其他线程只能一直等待,等待获取锁的线程释放锁,才能进入再次进入同步代码块。

获取锁的线程释放锁的情况只有两种:

  1. 正常执行完,然后释放锁。
  2. 执行过程中,发生异常,JVM让线程自动释放锁。

那么你试想一个如果获取到锁的这个线程,由于一些等待IO原因或其他原因被堵住了,但是又不能释放锁,其他线程就只能在synchronized的门口看着啦,你想一下这个效率吧,出现一次,可能就把人心态玩没啦哈。

上一篇:线程同步与线程方法及运行状态


下一篇:Java