zoukankan      html  css  js  c++  java
  • 加不加 synchronized 有什么区别?

    今天一起来认识认识 synchronized 这个一面试就会被提到的关键字。这一篇不会讲太多理论,主要先熟悉熟悉一下最简单的用法。只讨论一个问题:方法没用 synchronized 和用了 synchronized 有什么区别?

    首先我们的理论基础是 synchronized 关键字是用在多线程并发的场景,所以接下来的测试代码都会模拟多线程并发的情况。我们直接通过代码来给大家讲讲加没加 synchronized 的区别。

    1. 方法没加 synchronized 关键字

    我们先写一个普通到不能再普通的代码,就是一个实例方法,在多线程并发的情况下执行同一个方法。如下所示。

    public class NoSynchronizedTest {
    
        public static void main(String[] args) {
            NoSynchronizedTest noSynchronizedTest = new NoSynchronizedTest();
            for (int i = 0; i < 5; i ++) {
                Thread thread = new Thread(() -> {
                    noSynchronizedTest.testNoSynchronizedMethod();
                });
                thread.start();
            }
        }
    
        public void testNoSynchronizedMethod() {
            System.out.println("testNoSynchronizedMethod-start-" + Thread.currentThread().getName());
            System.out.println("testNoSynchronizedMethod-end-" + Thread.currentThread().getName());
        }
    
    }
    
    

    运行结果:

    我们可以发现如下结论:

    1. 在单线程中,执行顺序是有保证的,也就是每个 start 都优先于 end。
    2. 在多线程中,线程之间的 start 和 end 是没有先后顺序的,先进入方法的线程不一定先执行完方法。我们看运行结果的红色框,5 个线程只有 Thread-2 是完整的执行完方法,没有其他线程乱入的。

    2. 方法加 synchronized 关键字

    我们对上面的代码稍加修改,在方法上加 synchronized 修饰,并且在两种情况下执行代码。

    5 个线程只有一个 synchronizedTest 对象。

    public class SynchronizedTest {
    
        public static void main(String[] args) {
            SynchronizedTest synchronizedTest = new SynchronizedTest();
            for (int i = 0; i < 5; i++) {
                Thread thread = new Thread(() -> {
                    synchronizedTest.testSynchronizedMethod();
                });
                thread.start();
            }
        }
    
        public synchronized void testSynchronizedMethod() {
            System.out.println("testSynchronizedMethod-start-" + Thread.currentThread().getName());
            System.out.println("testSynchronizedMethod-end-" + Thread.currentThread().getName());
        }
    }
    

    运行结果:

    5 个线程中,每个线程有各自的 synchronizedTest 对象。

    public class SynchronizedTest {
    
        public static void main(String[] args) {
            for (int i = 0; i < 5; i++) {
                SynchronizedTest synchronizedTest = new SynchronizedTest();
                Thread thread = new Thread(() -> {
                    synchronizedTest.testSynchronizedMethod();
                });
                thread.start();
            }
        }
    
        public synchronized void testSynchronizedMethod() {
            System.out.println("testSynchronizedMethod-start-" + Thread.currentThread().getName());
            System.out.println("testSynchronizedMethod-end-" + Thread.currentThread().getName());
        }
    }
    

    运行结果:

    我们可以发现如下结论:

    1. 当 5 个线程中只有一个对象时,5 个线程之间的执行顺序是串行的,互不影响,线程0进入方法后,其他线程就无法再进入方法了,得等待线程0执行完后,其他线程才能进入,并且一次只能有1个线程进入。
    2. 每个线程一个对象时,就不会出现排队的场景,各个线程互不影响,相当于每个线程都有各自的资源,没有互相竞争的关系。

    由此,我们可以得出什么呢?synchronized 关键字就是悲观锁的具体实现,在多线程并发竞争同一资源时,实现同一时刻只有一个线程能操作资源。

    这篇文章是了解 synchronized 最最最皮毛的知识,对 synchronized 熟悉的朋友可以当做是回顾知识点,不熟悉的朋友可以当做是入门,后面会继续深挖知识点。

    如果觉得这篇文章看了有收获,麻烦点个在看,支持一下,原创不易。

    推荐阅读

    写了那么多年 Java 代码,终于 debug 到 JVM 了

    全网最新最简单的 openjdk13 代码编译

    了解Java线程优先级,更要知道对应操作系统的优先级,不然会踩坑

    线程最最基础的知识

    老板叫你别阻塞了

    吃个快餐都能学到串行、并行、并发

    泡一杯茶,学一学同异步

    进程知多少?

    设计模式看了又忘,忘了又看?

    后台回复『设计模式』可以获取《一故事一设计模式》电子书

    觉得文章有用帮忙转发&点赞,多谢朋友们!

    LieBrother

  • 相关阅读:
    poj 2377 Bad Cowtractors (最‘大’生成树)
    POJ 3626 Mud Puddles (BFS)
    hdu 3367 Pseudoforest (krusual)
    hdu 1548 A strange lift (bfs)
    poj 1860 Currency Exchange (Bellman_Ford)
    poj 1005 I Think I Need a Houseboat
    poj 3625 Building Roads (最小生成树)
    zoj 1586 QS Network (最小生成树)
    poj 1679 The Unique MST (最小生成树)
    .NET中书写XML的一种简单方法
  • 原文地址:https://www.cnblogs.com/liebrother/p/12776788.html
Copyright © 2011-2022 走看看