synchronized锁的是什么

最近发现synchronized锁的是什么?甚至有人认为synchronized锁的是代码??!这个我觉得还是很有必要通过实际的示例来说明synchronized锁的到底是什么。

根据获取的锁的分类:获取对象锁和获取类锁!

获取对象锁的两种用法

1、同步代码块(synchronized(this), synchronized(类实例对象)),锁是小括号()中的实例对象。 2、同步非静态方法(synchronized method),锁是当前对象的实例对象。

获取类锁的两种用法

1、同步代码块(synchronized(类.class)),锁是小括号()中的类对象,即Class对象。 2、同步静态方法(synchronized static method),锁是当前对象的类对象(Class对象)。

对象锁示例

看看这样一段代码:

SynchronizedDemo.java

 1package thread_study.synchronize;
 2
 3import java.text.SimpleDateFormat;
 4import java.util.Date;
 5import java.util.concurrent.TimeUnit;
 6
 7public class SynchronizedDemo implements Runnable{
 8
 9    @Override
10    public void run() {
11        String threadName = Thread.currentThread().getName();
12        if(threadName.startsWith("A")){
13            async();
14        }else if(threadName.startsWith("B")){
15            syncObjectBlock();
16        }else if(threadName.startsWith("C")){
17            syncObjectMethod();
18        }
19    }
20
21    private void async() {
22        try {
23            System.out.println(Thread.currentThread().getName()
24            + "_Async_Start:" 
25            + new SimpleDateFormat("mm:ss").format(new Date()));
26            
27            TimeUnit.SECONDS.sleep(1);
28            
29            System.out.println(Thread.currentThread().getName() 
30            + "_Async_End:" 
31            + new SimpleDateFormat("mm:ss").format(new Date()));
32            
33        } catch (InterruptedException e) {
34            e.printStackTrace();
35        }
36    }
37    private synchronized void syncObjectMethod() {
38        System.out.println(Thread.currentThread().getName() 
39        + "_SyncObjectMethod:" 
40        + new SimpleDateFormat("mm:ss").format(new Date()));
41        
42        try {
43            System.out.println(Thread.currentThread().getName() 
44            + "_SyncObjectMethod_Start:" 
45            + new SimpleDateFormat("mm:ss").format(new Date()));
46            
47            TimeUnit.SECONDS.sleep(1);
48            
49            System.out.println(Thread.currentThread().getName() 
50            + "_SyncObjectMethod_End:" 
51            + new SimpleDateFormat("mm:ss").format(new Date()));
52            
53        } catch (InterruptedException e) {
54            e.printStackTrace();
55        }
56    }
57
58    private void syncObjectBlock() {
59        System.out.println(Thread.currentThread().getName() 
60        + "_SyncObjectBlock:" 
61        + new SimpleDateFormat("mm:ss").format(new Date()));
62        synchronized (this){
63            try {
64                System.out.println(Thread.currentThread().getName() 
65                + "_SyncObjectBlock_Start:" 
66                + new SimpleDateFormat("mm:ss").format(new Date()));
67                
68                TimeUnit.SECONDS.sleep(1);
69                
70                System.out.println(Thread.currentThread().getName() 
71                + "_SyncObjectBlock_End:" 
72                + new SimpleDateFormat("mm:ss").format(new Date()));
73            } catch (InterruptedException e) {
74                e.printStackTrace();
75            }
76        }
77    }
78}

SynchronizedMain.java

 1package thread_study.synchronize;
 2
 3public class SynchronizedMain {
 4    public static void main(String[] args) {
 5        SynchronizedDemo demo = new SynchronizedDemo();
 6        Thread A_thread1 = new Thread(demo, "A_thread1");
 7        Thread A_thread2 = new Thread(demo, "A_thread2");
 8        Thread B_thread1 = new Thread(demo, "B_thread1");
 9        Thread B_thread2 = new Thread(demo, "B_thread2");
10        Thread C_thread1 = new Thread(demo, "C_thread1");
11        Thread C_thread2 = new Thread(demo, "C_thread2");
12        A_thread1.start();
13        A_thread2.start();
14
15        B_thread1.start();
16        B_thread2.start();
17
18        C_thread1.start();
19        C_thread2.start();
20    }
21}

mark

但是如果我们传入不同的对象呢?

 1package thread_study.synchronize;
 2
 3public class SynchronizedMain {
 4    public static void main(String[] args) {
 5        //SynchronizedDemo demo = new SynchronizedDemo();
 6        Thread A_thread1 = new Thread(new SynchronizedDemo(), "A_thread1");
 7        Thread A_thread2 = new Thread(new SynchronizedDemo(), "A_thread2");
 8        Thread B_thread1 = new Thread(new SynchronizedDemo(), "B_thread1");
 9        Thread B_thread2 = new Thread(new SynchronizedDemo(), "B_thread2");
10        Thread C_thread1 = new Thread(new SynchronizedDemo(), "C_thread1");
11        Thread C_thread2 = new Thread(new SynchronizedDemo(), "C_thread2");
12        A_thread1.start();
13        A_thread2.start();
14
15        B_thread1.start();
16        B_thread2.start();
17
18        C_thread1.start();
19        C_thread2.start();
20    }
21}

mark

从上面的代码和结果中我们可以得出一个结论,那就是

获取对象锁的两种用法: 1、同步代码块(synchronized(this), synchronized(类实例对象)),锁是小括号()中的实例对象。 2、同步非静态方法(synchronized method),锁是当前对象的实例对象。

同步非静态方法锁住整个方法,而同步代码块只是锁住的只是方法中的一部分代码

获取类锁的两种用法 1、同步代码块(synchronized(类.class)),锁是小括号()中的类对象,即Class对象。 2、同步静态方法(synchronized static method),锁是当前对象的类对象(Class对象)。

同步静态方法锁住整个方法,而同步代码块只是锁住的只是方法中的一部分代码,与上面一样的

类锁示例

下面来看看同步静态方法和同步代码块(synchronized(类.class))的效果吧:

 1package thread_study.synchronize;
 2
 3import java.text.SimpleDateFormat;
 4import java.util.Date;
 5import java.util.concurrent.TimeUnit;
 6
 7public class SynchronizedDemo implements Runnable{
 8
 9    @Override
10    public void run() {
11        String threadName = Thread.currentThread().getName();
12        if(threadName.startsWith("A")){
13            async();
14        }else if(threadName.startsWith("B")){
15            syncObjectBlock();
16        }else if(threadName.startsWith("C")){
17            syncObjectMethod();
18        }else if(threadName.startsWith("D")){
19            syncClassBlock();
20        }else if(threadName.startsWith("E")){
21            syncClassMethod();
22        }
23    }
24
25    private synchronized static void syncClassMethod() {
26        System.out.println(Thread.currentThread().getName()
27                           + "_SyncClassMethod:"
28                           + new SimpleDateFormat("mm:ss").format(new Date()));
29        try {
30            System.out.println(Thread.currentThread().getName()
31                               + "_SyncClassMethod_Start:"
32                               + new SimpleDateFormat("mm:ss").format(new Date()));
33            TimeUnit.SECONDS.sleep(1);
34            System.out.println(Thread.currentThread().getName()
35                               + "_SyncClassMethod_End:"
36                               + new SimpleDateFormat("mm:ss").format(new Date()));
37        } catch (InterruptedException e) {
38            e.printStackTrace();
39        }
40    }
41
42    private void syncClassBlock() {
43        System.out.println(Thread.currentThread().getName()
44                           + "_SyncClassBlock:" 
45                           + new SimpleDateFormat("mm:ss").format(new Date()));
46        synchronized (SynchronizedDemo.class){
47            try {
48                System.out.println(Thread.currentThread().getName()
49                                   + "_SyncClassBlock_Start:"
50                                   + new SimpleDateFormat("mm:ss").format(new Date()));
51                TimeUnit.SECONDS.sleep(1);
52                System.out.println(Thread.currentThread().getName()
53                                   + "_SyncClassBlock_End:" 
54                                   + new SimpleDateFormat("mm:ss").format(new Date()));
55            } catch (InterruptedException e) {
56                e.printStackTrace();
57            }
58        }
59    }
60
61    private void async() {
62        try {
63            System.out.println(Thread.currentThread().getName() 
64                               + "_Async_Start:" 
65                               + new SimpleDateFormat("mm:ss").format(new Date()));
66            TimeUnit.SECONDS.sleep(1);
67            System.out.println(Thread.currentThread().getName() 
68                               + "_Async_End:" 
69                               + new SimpleDateFormat("mm:ss").format(new Date()));
70        } catch (InterruptedException e) {
71            e.printStackTrace();
72        }
73    }
74    //...和上面一样的
75}

SynchronizedMain.java

 1package thread_study.synchronize;
 2
 3public class SynchronizedMain {
 4    public static void main(String[] args) {
 5        Thread A_thread1 = new Thread(new SynchronizedDemo(), "A_thread1");
 6        Thread A_thread2 = new Thread(new SynchronizedDemo(), "A_thread2");
 7        Thread D_thread1 = new Thread(new SynchronizedDemo(), "D_thread1");
 8        Thread D_thread2 = new Thread(new SynchronizedDemo(), "D_thread2");
 9        Thread E_thread1 = new Thread(new SynchronizedDemo(), "E_thread1");
10        Thread E_thread2 = new Thread(new SynchronizedDemo(), "E_thread2");
11
12        A_thread1.start();
13        A_thread2.start();
14
15        D_thread1.start();
16        D_thread2.start();
17        E_thread1.start();
18        E_thread2.start();
19    }
20}

mark

对象锁和类锁不会干扰

最后看看类锁和对象锁是否会相互影响呢?

修改一下代码:

 1package thread_study.synchronize;
 2
 3public class SynchronizedMain {
 4    public static void main(String[] args) {
 5        //SynchronizedDemo demo = new SynchronizedDemo();
 6        Thread A_thread1 = new Thread(new SynchronizedDemo(), "A_thread1");
 7        Thread A_thread2 = new Thread(new SynchronizedDemo(), "A_thread2");
 8        Thread B_thread1 = new Thread(new SynchronizedDemo(), "B_thread1");
 9        Thread B_thread2 = new Thread(new SynchronizedDemo(), "B_thread2");
10        Thread C_thread1 = new Thread(new SynchronizedDemo(), "C_thread1");
11        Thread C_thread2 = new Thread(new SynchronizedDemo(), "C_thread2");
12        Thread D_thread1 = new Thread(new SynchronizedDemo(), "D_thread1");
13        Thread D_thread2 = new Thread(new SynchronizedDemo(), "D_thread2");
14        Thread E_thread1 = new Thread(new SynchronizedDemo(), "E_thread1");
15        Thread E_thread2 = new Thread(new SynchronizedDemo(), "E_thread2");
16
17        A_thread1.start();
18        A_thread2.start();
19
20        B_thread1.start();
21        B_thread2.start();
22        C_thread1.start();
23        C_thread2.start();
24
25        D_thread1.start();
26        D_thread2.start();
27        E_thread1.start();
28        E_thread2.start();
29    }
30}

mark

可以看出来,类锁和对象锁是不会相互干扰的!