synchronized 作用在普通方法与静态方法的区别

synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种: 
1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象; 
2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象; 
3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象; 
4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package  com.fyb.concurrent;
 
public  class  SynchronizedTest {
     
     private  int  num;
     
     public  synchronized  void  method01(String arg) {
         try  {
             if ( "a" .equals(arg)){
                 num =  100 ;
                 System.out.println( "tag a set number over" );
                 Thread.sleep( 1000 );
             } else {
                 num =  200 ;
                 System.out.println( "tag b set number over" );
             }
             
             System.out.println( "tag = " + arg +  ";num =" + num);
         catch  (InterruptedException e) {
             e.printStackTrace();
         }
     }
 
     public  static  void  main(String[] args) {
         final  SynchronizedTest m1 =  new  SynchronizedTest();
         final  SynchronizedTest m2 =  new  SynchronizedTest();
         
         Thread t1 =  new  Thread( new  Runnable() {
             
             @Override
             public  void  run() {
                 m1.method01( "a" );
             }
         });
         t1.start();
         
         Thread t2 =  new  Thread( new  Runnable() {
             
             @Override
             public  void  run() {
                 m2.method01( "b" );
             }
         });
         t2.start();
         
     }
}

执行输出:

1
2
3
4
tag a set number over
tag b set number over
tag = b;num =200
tag = a;num =100

可以看出,两个不同的对象m1和m2的method01()方法执行并没有互斥,因为这里synchronized是分别持有两个对象的锁。如果要想m1,m2两个对象竞争同一个锁,则需要在method01()上加上static修饰。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package  com.fyb.concurrent;
 
public  class  SynchronizedTest {
     
     private  static  int   num;
     
     public  static  synchronized  void  method01(String arg) {
         try  {
             if ( "a" .equals(arg)){
                 num =  100 ;
                 System.out.println( "tag a set number over" );
                 Thread.sleep( 1000 );
             } else {
                 num =  200 ;
                 System.out.println( "tag b set number over" );
             }
             
             System.out.println( "tag = " + arg +  ";num =" + num);
         catch  (InterruptedException e) {
             e.printStackTrace();
         }
     }
 
     public  static  void  main(String[] args) {
         final  SynchronizedTest m1 =  new  SynchronizedTest();
         final  SynchronizedTest m2 =  new  SynchronizedTest();
         
         Thread t1 =  new  Thread( new  Runnable() {
             
             @Override
             public  void  run() {
                 m1.method01( "a" );
             }
         });
         t1.start();
         
         Thread t2 =  new  Thread( new  Runnable() {
             
             @Override
             public  void  run() {
                 m2.method01( "b" );
             }
         });
         t2.start();
         
     }
}

输出结果:

1
2
3
4
tag a set number over
tag = a;num =100
tag b set number over
tag = b;num =200

小结:

synchronized修饰不加static的方法,锁是加在单个对象上,不同的对象没有竞争关系;修饰加了static的方法,锁是加载类上,这个类所有的对象竞争一把锁。

猜你喜欢

转载自blog.csdn.net/qq_33363618/article/details/80567374