Java synchronized 关键字详解

  Javasynchronized关键字详解
  前置技能点
  进程和线程的概念
  线程创立方式
  线程的状态状态转换
  线程安全的概念
  synchronized关键字的几种用法
  润饰非静态成员办法
  synchronizedpublicvoidsync(){
  }
  润饰静态成员办法
  synchronizedpublicstaticvoidsync(){
  }
  类锁代码块
  synchronized(类.class){
  }
  目标锁代码块
  synchronized(this|目标){
  }
  synchronized润饰非静态办法时能够看做是锁this目标,润饰静态办法时能够看做是锁办法地点的类。
  synchronized关键字的根本机制
  各个线程想要拜访被synchronized润饰的代码块,就要取得synchronized声明的锁。假如两个线程的目标是同一个锁,就会呈现阻塞的现象,所以两个线程不能同时拜访同一个锁下的代码,保证了多线程在履行时终究成果不会犯错。这与同享变量是否为静态无关。java手写多级缓存
  几个比如
  目标锁
  publicclassThreadDemoextendsThread{@Overridepublicsynchronizedvoidrun(){for(inti=0;i<10000;i++){
  Main.i++;
  }
  System.out.println(“履行完结”);
  }
  }
  直接将承继的run()办法标记为synchronized,作用是对Main类中的i变量做10000次累加操作。
  publicclassMain{staticinti=0;publicstaticvoidmain(String[]args)throwsInterruptedException{
  ThreadDemothreadDemo=newThreadDemo();
  Threadt1=newThread(threadDemo);
  Threadt2=newThread(threadDemo);
  Threadt3=newThread(threadDemo);
  Threadt4=newThread(threadDemo);
  t1.start();
  t2.start();
  t3.start();
  t4.start();
  t1.join();
  t2.join();
  t3.join();
  t4.join();
  System.out.println(i);
  }
  }//输出成果://履行完结//履行完结//履行完结//履行完结//40000
  能够看到当4个线程悉数履行结束之后,变量i成功的累加了40000次,没有呈现丢失操作的状况。
  假如咱们将main()办法修正如下:
  publicstaticvoidmain(String[]args)throwsInterruptedException{
  Threadt1=newThreadDemo();
  Threadt2=newThreadDemo();
  Threadt3=newThreadDemo();
  Threadt4=newThreadDemo();
  t1.start();
  t2.start();
  t3.start();
  t4.start();
  t1.join();
  t2.join();
  t3.join();
  t4.join();
  System.out.println(i);
  }//输出成果://履行完结//履行完结//履行完结//履行完结//27579
  能够看到丢失了不少的累加操作。调查前后两个main()办法创立线程的方式能够发现,前面的main()办法是使用了同一个目标来创立了4个不同的线程,而后一个main()办法使用了4个不同的ThreadDemo目标创立了4个线程。咱们用synchronized润饰的是一个非静态成员函数,相当于对该办法创立了this的目标锁。在第一个main()办法中使用同一个目标来创立4个不同线程就会让4个线程抢夺同一个目标锁,这样,在同一时间内,仅能有一个线程能拜访synchronized润饰的办法。而在第二种main()办法中,4个线程各自对应一个目标锁,4个线程之间没有竞赛关系,目标锁自然无法收效。
  类锁
  publicclassThreadDemoextendsThread{@Overridepublicvoidrun(){synchronized(ThreadDemo.class){for(inti=0;i<10000;i++){
  Main.i++;
  }
  System.out.println(“履行完结”);
  }
  }
  }
  将润饰办法的synchronized改为对ThreadDemo.class上锁的代码块
  publicclassThreadDemo2extendsThread{@Overridepublicvoidrun(){synchronized(ThreadDemo2.class){for(inti=0;i<10000;i++){
  Main.i++;
  }
  System.out.println(“履行完结”);
  }
  }
  }
  再创立一个相同的类命名为ThreadDemo2,与ThreadDemo不同的是,ThreadDemo2中,synchronized对ThreadDemo2.class上锁。
  publicstaticvoidmain(String[]args)throwsInterruptedException{
  Threadt1=newThreadDemo();
  Threadt2=newThreadDemo();
  Threadt3=newThreadDemo2();
  Threadt4=newThreadDemo2();
  t1.start();
  t2.start();
  t3.start();
  t4.start();
  t1.join();
  t2.join();
  t3.join();
  t4.join();
  System.out.println(i);
  }//输出成果://履行完结//履行完结//履行完结//履行完结//33054
  4个线程别离由ThreadDemo和ThreadDemo2来创立,明显得到的成果与预期的40000不符。假如咱们将ThreadDemo2中的synchronized改为对ThreadDemo.class上锁:
  publicclassThreadDemo2extendsThread{@Overridepublicvoidrun(){synchronized(ThreadDemo.class){for(inti=0;i<10000;i++){
  Main.i++;
  }
  System.out.println(“履行完结”);
  }
  }
  }//输出成果://履行完结//履行完结//履行完结//履行完结//40000
  能够看到,虽然是声明在两个不同的类中的synchronized代码块,可是由于都是对ThreadDemo.class上锁,所以4个线程之间还是建立了竞赛关系,同时只能有一个线程拜访被synchronized润饰的代码。
  总结
  所以synchronized关键字的本质是约束线程拜访一段代码,而约束的条件就是,在所有被加上相同锁的代码上,同一时间,只能有一个线程在运行。这与你要修正什么样的同享变量无关。在我刚接触到的时候认为类锁和目标锁是别离针对静态同享变量和非静态同享变量的,但事实上锁的是要履行的代码块,而不是代码块即将拜访的同享变量。

来源:https://zzzjtd.com/5458.html

你可能感兴趣的:(Java synchronized 关键字详解)