`

synchronized的作用

阅读更多

一、同步方法

public synchronized void methodAAA(){

//….

}
锁定的是调用这个同步方法的对象

测试:
a、不使用这个关键字修饰方法,两个线程调用同一个对象的这个方法。
目标类:

1 public   class  TestThread  {
2      public    void  execute() {   // synchronized,未修饰
3          for ( int  i = 0 ;i < 100 ;i ++ ) {
4             System.out.println(i);
5         }
    
6     }

7 }


线程类:

1 public   class  ThreadA  implements  Runnable {
2     TestThread test = null ;
3      public  ThreadA(TestThread pTest) {   // 对象有外部引入,这样保证是同一个对象
4         test = pTest;
5     }

6      public   void  run()  {
7         test.execute();
8     }

9 }


调用:

1 TestThread test = new  TestThread();
2 Runnable runabble = new  ThreadA(test);
3 Thread a = new  Thread(runabble, " A " );                
4 a.start();
5 Thread b = new  Thread(runabble, " B " );
6 b.start();


结果:
输出的数字交错在一起。说明不是同步的,两个方法在不同的线程中是异步调用的。

b、修改目标类,增加synchronized修饰

1 public   class  TestThread  {
2      public   synchronized    void  execute() {   // synchronized修饰
3          for ( int  i = 0 ;i < 100 ;i ++ ) {
4             System.out.println(i);
5         }
    
6     }

7 }


结果:
输出的数字是有序的,首先输出A的数字,然后是B,说明是同步的,虽然是不同的线程,但两个方法是同步调用的。
注意:上面虽然是两个不同的线程,但是是同一个实例对象。下面使用不同的实例对象进行测试。

c、每个线程都有独立的TestThread对象。
目标类:

1 public   class  TestThread  {
2      public   synchronized   void  execute() {   // synchronized修饰
3          for ( int  i = 0 ;i < 100 ;i ++ ) {
4             System.out.println(i);
5         }
    
6     }

7 }


线程类:

1 public   class  ThreadA  implements  Runnable {
2      public   void  run()  {
3         TestThread test = new  TestThread();
4         test.execute();
5     }

6 }

7


调用:

1 Runnable runabble = new  ThreadA();
2 Thread a = new  Thread(runabble, " A " );                
3 a.start();
4 Thread b = new  Thread(runabble, " B " );
5 b.start();


结果:
输出的数字交错在一起。说明虽然增加了synchronized 关键字来修饰方法,但是不同的线程调用各自的对象实例,两个方法仍然是异步的。

引申:
对于这种多个实例,要想实现同步即输出的数字是有序并且按线程先后顺序输出,我们可以增加一个静态变量,对它进行加锁(后面将说明锁定的对象)。

修改目标类:

 1 public   class  TestThread  {
 2      private   static  Object lock = new  Object();  // 必须是静态的。
 3      public    void  execute() {
 4          synchronized (lock) {
 5              for ( int  i = 0 ;i < 100 ;i ++ ) {
 6                 System.out.println(i);
 7             }
    
 8         }

 9     }

10 }

二、同步代码块

1 public   void  method(SomeObject so) {
2      synchronized (so)
3         // …..
4     }

5 }

锁定一个对象,其实锁定的是该对象的引用(object reference)
谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以按上面的代码写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它必须是一个对象)来充当锁(上面的解决方法就是增加了一个状态锁)。

a、锁定一个对象,它不是静态的
private byte[] lock = new byte[0]; // 特殊的instance变量
目标类:

 1 public   class  TestThread  {
 2      private  Object lock = new  Object(); 
 3      public    void  execute() {
 4          synchronized (lock) {   // 增加了个锁,锁定了对象lock,在同一个类实例中,是线程安全的,但不同的实例还是不安全的。
 5
 6 因为不同的实例有不同对象锁lock
 7              for ( int  i = 0 ;i < 100 ;i ++ ) {
 8                 System.out.println(i);
 9             }
    
10         }

11     }

12 }
  


其实上面锁定一个方法,等同于下面的:

1 public   void  execute() {  
2      synchronized ( this ) {    // 同步的是当然对象
3          for ( int  i = 0 ;i < 100 ;i ++ ) {
4             System.out.println(i);
5         }
    
6     }

7 }

b、锁定一个对象或方法,它是静态的
这样锁定,它锁定的是对象所属的类
public synchronized  static void execute(){
    //...
}
等同于

1 public   class  TestThread  {
2      public   static   void  execute() {
3          synchronized (TestThread. class ) {
4              //
5         }

6     }

7 }

测试:

目标类:

 1 public   class  TestThread  {
 2      private   static  Object lock = new  Object();
 3      public   synchronized   static   void  execute() {   // 同步静态方法
 4          for ( int  i = 0 ;i < 100 ;i ++ ) {
 5             System.out.println(i);
 6         }
    
 7     }

 8      public   static   void  execute1() {
 9          for ( int  i = 0 ;i < 100 ;i ++ ) {
10             System.out.println(i);
11         }
    
12     }

13      public   void  test() {
14         execute();      // 输出是有序的,说明是同步的
15          // execute1();   // 输出是无须的,说明是异步的
16     }

17 }

线程类:调用不同的方法,于是建立了两个线程类

 1 public   class  ThreadA  implements  Runnable {
 2      public   void  run()  {
 3         TestThread.execute(); // 调用同步静态方法
 4     }

 5 }

 6 public   class  ThreadB  implements  Runnable {
 7      public   void  run()  {
 8         TestThread test = new  TestTh
分享到:
评论

相关推荐

    Java关键字volatile和synchronized作用和区别

    主要为大家详细介绍了Java关键字volatile和synchronized的作用和区别,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

    【Java】synchronized同步锁详解

    synchronized同步锁(悲观锁)2.1 synchronized 作用范围2.2 synchronized 核心组件2.3 synchronized 实现 1. Java锁的种类 1.1 乐观锁 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低。 每次去拿...

    Java synchronized详细解读.docx

    如果 再细的分类,synchronized可作用于instance变量、object reference(对象引用)、static函数和class literals(类名称字面常量)身上。 无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而...

    Android多线程之同步锁的使用

    当synchronized作用于函数时,实际上锁的也是对象,锁定的对象就是该函数所在类的对象。而synchronized作用于class时则是锁的这个Class类,并非具体对象。 public class SynchronizedClass { public synchronized ...

    synchronized关键字的用法详解

    synchronized关键字在java中的重要性 以及常用的方法 还有它的详解

    JAVA核心知识点整理(有效)

    1. 目录 1. 2. 目录 .........................................................................................................................................................1 JVM ........................

    java核心知识点整理.pdf

    1. 目录 1. 2. 目录 .........................................................................................................................................................1 JVM .........................

    Java synchronized 详解.docx

    如果 再细的分类,synchronized可作用于instance变量、object reference(对象引用)、static函数和class literals(类名称字面常量)身上。 无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而...

    实例解析Java中的synchronized关键字与线程安全问题

    synchronized代码块,被修饰的代码成为同步语句块,其作用的范围是调用这个代码块的对象,我们在用synchronized关键字的时候,能缩小代码段的范围就尽量缩小,能在代码段上加同步就不要再整个方法上加同步。...

    lock锁,lock锁和synchronized的对比

    Lock是显式锁,需要手动的开启和关闭,synchronized锁是隐式锁,只要出了作用域就会自动释放。Lock只有代码块锁,synchronized既有代码块锁还有方法锁。 使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。有...

    Java并发编程:Synchronized及其实现原理

    Synchronized的作用主要有三个:(1)确保线程互斥的访问同步代码(2)保证共享变量的修改能够及时可见(3)有效解决重排序问题。从语法上讲,Synchronized总共有三种用法:  (1)修饰普通方法  (2)修饰静态...

    javalruleetcode-Android-interview-knowledge:Android-面试知识

    synchronized 作用,修饰不同的时候的作用 16. GC算法 17.Android应用开发之所有动画使用详解 18.图解Android - Android GUI 系统 (1) - 概论 19.Android性能优化 20.Android Material Design GCRoot 都有哪些? 1、...

    深入理解Java并发之synchronized实现原理.docx

    关键字 synchronized可以保证在同一个时刻,只有一个线程可以执行某个方法或者某个代码块(主要是对方法或者代码块中存在共享数据的操作),同时我们还应该注意到synchronized另外一个重要的作用,synchronized可保证...

    Java中synchronized的用法

    本文将接着讲一下Java线程同步中的一个重要的概念synchronized.  synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:  1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大...

    关于线程同步

    ――还得对synchronized关键字的作用进行深入了解才可定论。 总的说来,synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。如果再细的分 类,synchronized可...

    Java同步机制浅谈

    Java 对多线程的支持与同步机制深受大家的喜爱,似乎看起来使用了...如果再细的分类,synchronized 可作用于instance 变量、 object reference(对象引用)、static 函数和class literals(类名称字面常量)身上。

    Dynamic Synchronized Phasor Measurement based on AM-FM Demodulation

    基于幅频联合调制解调的动态同步相量测量算法,靳夏宁,汪芙平,利用同步相量测量单元对同步相量的精确估计,对于电力系统分析、控制和安全运行都有十分重大的作用。近期的研究对动态条件下的相

    Java 同步锁 wait notify 学习心得

    java多线程下wait和notify的作用

    20道JAVA面试题.docx

    20道JAVA面试题 1、Java中的包是什么? 2、Java中的访问修饰符有哪些?它们的作用是什么? 3、Java中的final关键字有...8、Java中的synchronized关键字有什么作用? 9、Java中的异常是什么? 10、Java中的泛型是什么?

    大厂真题之字节跳动-Java初级

    synchronized 可以修饰的作用域如下: - 非静态方法(加的锁为对象锁); - 静态方法(加的锁为类锁); - 代码块(对象锁与类锁均可); 2. Lock 采用 lock()对代码加锁,unlock()进行解锁 参考文章:...

Global site tag (gtag.js) - Google Analytics