专栏首页用户7113604的专栏一个例子讲Synchronized关键字
原创

一个例子讲Synchronized关键字

引言

文中的例子从线程调度上讲不够严谨。原因是没输出,并不代表线程无法进入方法,有可能是线程一直没有被调度。

不过拿来讲Synchronized是可以的,因为两个有竞争线程,输出结果必然是先进入的线程输出完并且退出方法后,另一个才能输出

例子

   public class SycTest {

     private Object ob = new Object();

   

     static synchronized void abc(String x){

       print(x);

     }

     synchronized void cde(String y){

       print(y);

     }

   

     synchronized void def(String y){

       print(y);

     }

   

     void fgh(String z){

       synchronized (ob){

         print(z);

       }

     }

   

     static void print(String c){

       for(int i=0;i<4 ;i++){

         System.out.print(c+",");

         try {

           Thread.sleep(1000);

         } catch (InterruptedException e) {

           e.printStackTrace();

         }

       }

     }

     public static void main(String[] args) throws InterruptedException {

       SycTest test = new SycTest();

       Thread t1 = new Thread(()->{test.cde("t1");});

       Thread t2 = new Thread(()->{test.def("t2");});

       Thread t3 = new Thread(()->{abc("t3");});

       Thread t4 = new Thread(()->{test.cde("t4");});

       Thread t5 = new Thread(()->{test.fgh("t5");});

      

       List<Thread> threads = new ArrayList<>(5);

       threads.add(t1);

       threads.add(t2);

       threads.add(t3);

       threads.add(t4);

       threads.add(t5);

       threads.parallelStream().forEach(t->t.start());

     }

   }

跑几次后,代码输出结果

t3,t2,t5,t3,t2,t5,t3,t2,t5,t3,t5,t2,t1,t1,t1,t1,t4,t4,t4,t4,

t3,t5,t4,t3,t4,t5,t3,t5,t4,t3,t5,t4,t1,t1,t1,t1,t2,t2,t2,t2,

t3,t2,t5,t5,t2,t3,t2,t5,t3,t2,t5,t3,t4,t4,t4,t4,t1,t1,t1,t1,

t3,t1,t5,t3,t1,t5,t3,t1,t5,t3,t1,t5,t4,t4,t4,t4,t2,t2,t2,t2,

我们可以看到

t1的4次输出后t4才有机会输出或者相反。(同一个synchronized方法一次只能由一个线程执行)

t1(4)的4次输出后t2才有机会输出或者相反。(同一个实例的synchronized方法一次只能由一个线程执行)

t3的能够及时输出,没有一定的先后顺序。(synchronized修饰的static方法和实例方法可以同时执行,并不冲突。)

t5的能够及时输出,没有一定的先后顺序。(why)

解释

上面4点的解释,也算是java基础之一

1.synchronized修饰的实例方法是对当前对象实例加锁。

2.基于第1点,同一对象实例的不同synchronized方法不能同时执行,所以现实中应做好考虑。

3.synchronized修饰的static方法其实锁定的当前对象的Class对象,而Class对象只有一个。

4.synchronized块中,明确指定了synchronized的锁定的对象,就可能不会受第1点描述的影响。如果synchronized(this)的话就相当于第1点。

5.基于第3点,一个类中的两个synchronized修饰的static方法不能同时执行。

引申

关于synchronized(this)和第5点自行写例子验证。

想深入synchronized在JVM层面上的实现可以参考"死磕Synchronized底层实现" 概论链接https://juejin.im/post/5bfe6ddee51d45491b0163eb

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • ReentranLock源码浅析

    常用的lock方法具体实现是在FairSync和NonfairSync。Nonfaire体现在lock时尝试直接获取锁,如果获取失败,则使用和公平锁一样通过Ab...

    小金狗子
  • Java ClassLoader加载class过程

    关于class loader有太多太多的文章和图来讲过程。我就不多说了。以下是我认为的一些要点。

    小金狗子
  • ReentranReadWriteLock源码浅析

    c指的AbstractQueuedSynchronizer的state。SHARED_UNIT为65536。

    小金狗子
  • 多线程基础(十二):Thread优先级分析

    在前面学习Thread源码的时候,提到了Thread可以设置优先级。其优先级通过setPriority方法进行设置。

    冬天里的懒猫
  • 深入理解java异常处理机制

     1. 引子        try…catch…finally恐怕是大家再熟悉不过的语句了,而且感觉用起来也是很简单,逻辑上似乎也是很容易理解。不过,...

    大闲人柴毛毛
  • 深入理解java异常处理机制

    http://blog.csdn.net/hguisu/article/details/6155636

    bear_fish
  • 记录一个try catch没有生效的原因,以便备忘

    为了测试方便,直接建立的MFC对话框工程,直接选择Release编译。在代码中测试发现,添加了try catch之后,运行程序出现异常时仍然报错,而没有catc...

    大菊观
  • Flutter 中的本地存储

    在Flutter中,我们使用shared_preferences组件来实现本地数据的存储。

    拉维
  • 黑客声称窃取GitHub 500GB源代码,准备不出售直接泄露

    “我们已经成功入侵微软的GitHub私人储存库,并从中窃取了500GB的数据,本来打算在暗网上出售的,现在改变主意了,打算免费发布。”

    FB客服
  • JDK1.7新特性(2):异常和可变长参数处理

    异常 jdk1.7对try--catch--finally的异常处理模式进行了增强,下面我们依次来看增强的方面。   1. 为了防止异常覆盖,给Throwab...

    SecondWorld

扫码关注云+社区

领取腾讯云代金券