Java高并发 Synchronized详解(二)

释放双眼,带上耳机,听听看~!

1.1、两个线程同时访问一个对象的同步方法


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
1//两个线程 t1,t2 同时访问SynchronizedObjectMethod3对象中的Method()方法:
2package disappear.request;
3
4public class SynchronizedObjectMethod3 implements Runnable{
5    static SynchronizedObjectMethod3 instence = new SynchronizedObjectMethod3();
6    @Override
7    public void run() {
8            Method();
9    }
10    //争抢的是同一把锁
11    public synchronized void Method() {
12        System.out.println("My name is :"+Thread.currentThread().getName());
13        try{
14            Thread.sleep(3000);
15        }catch(InterruptedException ie){
16            ie.printStackTrace();
17        }
18        System.out.println(Thread.currentThread().getName()+" is over!");
19    }
20    public static void main(String [] args){
21        Thread t1 = new Thread(instence);
22        Thread t2 = new Thread(instence);
23        t1.start();
24        t2.start();
25        while(t1.isAlive()||t2.isAlive()){
26        }
27        System.out.println("Over!");
28    }
29}
30
31
32

1.2、两个线程同时访问两个对象的同步(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
1//两个线程 t1,t2 分别访问的是两个Phenomenon1对象中的Method()方法
2package Synchronized.Seven.Phenomenon;
3
4public class Phenomenon1 implements Runnable{
5    static Phenomenon1 instence1 = new Phenomenon1();
6    static Phenomenon1 instence2 = new Phenomenon1();
7    public synchronized void Method(){
8        System.out.println("My name is:"+Thread.currentThread().getName());
9        try {
10            Thread.sleep(3000);
11        } catch (InterruptedException e) {
12            e.printStackTrace();
13        }
14        System.out.println(Thread.currentThread().getName()+" is over!");
15    }
16    @Override
17    public void run() {
18        Method();
19    }
20    public static void main(String [] args){
21        Thread  t1 = new Thread(instence1);
22        Thread  t2 = new Thread(instence2);
23        t1.start();
24        t2.start();
25        while(t1.isAlive()||t2.isAlive()){
26            
27        }
28        System.out.println("all is over!");
29    }
30}
31
32

1.3、两个线程访问的是不同对象的同步(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
1//两个线程 t1,t2 分别访问的是两个Phenomenon1对象中的Method()方法,但是Method()方法是静态方法。
2package Synchronized.Seven.Phenomenon;
3
4public class Phenomenon3 implements Runnable{
5    static Phenomenon3 instence1 = new Phenomenon3();
6    static Phenomenon3 instence2 = new Phenomenon3();
7    public static synchronized void Method(){
8        System.out.println("My name is:"+Thread.currentThread().getName());
9        try {
10            Thread.sleep(3000);
11        } catch (InterruptedException e) {
12            e.printStackTrace();
13        }
14        System.out.println(Thread.currentThread().getName()+" is over!");
15    }
16    @Override
17    public void run() {
18        Method();
19    }
20    public static void main(String [] args){
21        Thread  t1 = new Thread(instence1);
22        Thread  t2 = new Thread(instence2);
23        t1.start();
24        t2.start();
25        while(t1.isAlive()||t2.isAlive()){
26
27        }
28        System.out.println("all is over!");
29    }
30}
31
32

1.4、同时访问同步方法和非同步方法


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
1//两个线程 t1,t2 访问的是一个Phenomenon4对象中的Method1()方法和Method2()方法,但是Method1()方法由synchronized修饰。
2package Synchronized.Seven.Phenomenon;
3
4public class Phenomenon4 implements Runnable
5{
6    static Phenomenon4 instence = new Phenomenon4();
7    public synchronized void Method1() {
8        System.out.println("I'm a method by synchronized,my name is:"+Thread.currentThread().getName());
9        try {
10            Thread.sleep(3000);
11        } catch (InterruptedException e) {
12            e.printStackTrace();
13        }
14        System.out.println(Thread.currentThread().getName()+"is over!");
15    }
16    public void Method2() {
17        System.out.println("I'm a commend method,my name is:"+Thread.currentThread().getName());
18        try {
19            Thread.sleep(3000);
20        } catch (InterruptedException e) {
21            e.printStackTrace();
22        }
23        System.out.println(Thread.currentThread().getName()+"is over!");
24    }
25    @Override
26    public void run() {
27        if(Thread.currentThread().getName().equals("Thread-0")){
28            Method1();
29        }else{
30            Method2();
31        }
32    }
33    public static void main(String[] args){
34        Thread t1 = new Thread(instence);
35        Thread t2 = new Thread(instence);
36        t1.start();
37        t2.start();
38        while(t1.isAlive()||t2.isAlive()){
39            
40        }
41        System.out.println("all is over!");
42    }
43}
44
45

结论:synchronized 关键字只作用于修饰的一个方法,不会影响同类中的其他方法的并发操作。

1.5、访问同一个对象的不同普通同步方法


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
1//两个线程 t1,t2 访问的是一个Phenomenon5对象中的Method1()方法和Method2()方法,两个方法都被synchronized修饰。
2package Synchronized.Seven.Phenomenon;
3
4public class Phenomenon5 implements Runnable{
5    static Phenomenon5 instence = new Phenomenon5();
6    public synchronized void Method1() {
7        System.out.println("I'm a method by synchronized,my name is:"+Thread.currentThread().getName());
8        try {
9            Thread.sleep(3000);
10        } catch (InterruptedException e) {
11            e.printStackTrace();
12        }
13        System.out.println(Thread.currentThread().getName()+"is over!");
14    }
15    public synchronized void Method2() {
16        System.out.println("I'm a method by synchronized,my name is:"+Thread.currentThread().getName());
17        try {
18            Thread.sleep(3000);
19        } catch (InterruptedException e) {
20            e.printStackTrace();
21        }
22        System.out.println(Thread.currentThread().getName()+"is over!");
23    }
24    @Override
25    public void run() {
26        if(Thread.currentThread().getName().equals("Thread-0")){
27            Method1();
28        }else{
29            Method2();
30        }
31    }
32    public static void main(String [] args){
33        Thread t1 = new Thread(instence);
34        Thread t2 = new Thread(instence);
35        t1.start();
36        t2.start();
37        while(t1.isAlive()||t2.isAlive()){
38
39        }
40        System.out.println("all is over!");
41    }
42}
43
44

结论:synchronized默认指定了this这个对象,作为他的锁。所以synchronized修饰的两个或者两个以上的方法是相互受到影响的。

1.6、同时访问静态的synchronized方法和非静态的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
1//两个线程 t1,t2 访问的是一个Phenomenon6对象中的Method1()方法和Method2()方法,两个方法都被synchronized修饰,但是Method1()方法是静态方法,Method2()方法是非静态方法
2package Synchronized.Seven.Phenomenon;
3
4public class phenomenon6 implements Runnable{
5    static phenomenon6 instence = new phenomenon6();
6    //static修饰的背后'锁'是.class对象
7    public static synchronized void Method1() {
8        System.out.println("I'm a synchronized and static method,my name is:"+Thread.currentThread().getName());
9        try {
10            Thread.sleep(3000);
11        } catch (InterruptedException e) {
12            e.printStackTrace();
13        }
14        System.out.println(Thread.currentThread().getName()+"is over!");
15    }
16    //没有静态修饰,'锁'是t实例本身his对象.
17    public synchronized void Method2() {
18        System.out.println("I'm a synchronized method ,my name is:"+Thread.currentThread().getName());
19        try {
20            Thread.sleep(3000);
21        } catch (InterruptedException e) {
22            e.printStackTrace();
23        }
24        System.out.println(Thread.currentThread().getName()+"is over!");
25    }
26    @Override
27    public void run() {
28        if(Thread.currentThread().getName().equals("Thread-0")){
29            Method1();
30        }else{
31            Method2();
32        }
33    }
34    public static void main(String [] args){
35        Thread t1 = new Thread(instence);
36        Thread t2 = new Thread(instence);
37        t1.start();
38        t2.start();
39        while(t1.isAlive()||t2.isAlive()){
40        }
41        System.out.println("all is over!");
42    }
43}
44
45

结论:静态synchronized修饰的方法和非静态synchronized修饰的方法,之间所获取到的 ’ 锁 ’ 是不相同的。所以两者之间没有影响。

1.7、方法抛出异常后,会释放锁


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
48
1//
2package Synchronized.Seven.Phenomenon;
3
4public class Phenomenon7 implements Runnable{
5    static Phenomenon7 instence = new Phenomenon7();
6    //static修饰的背后'锁'是.class对象
7    public synchronized void Method1() {
8        System.out.println("I'm a synchronized and static method,my name is:"+Thread.currentThread().getName());
9        try {
10            Thread.sleep(3000);
11            throw new Exception();
12        } catch (InterruptedException e) {
13            e.printStackTrace();
14        } catch (Exception e) {
15            e.printStackTrace();
16        }
17        System.out.println(Thread.currentThread().getName()+"is over!");
18    }
19    //没有静态修饰,'锁'是t实例本身his对象.
20    public synchronized void Method2() {
21        System.out.println("I'm a synchronized method ,my name is:"+Thread.currentThread().getName());
22        try {
23            Thread.sleep(3000);
24        } catch (InterruptedException e) {
25            e.printStackTrace();
26        }
27        System.out.println(Thread.currentThread().getName()+"is over!");
28    }
29    @Override
30    public void run() {
31        if(Thread.currentThread().getName().equals("Thread-0")){
32            Method1();
33        }else{
34            Method2();
35        }
36    }
37    public static void main(String [] args){
38        Thread t1 = new Thread(instence);
39        Thread t2 = new Thread(instence);
40        t1.start();
41        t2.start();
42        while(t1.isAlive()||t2.isAlive()){
43        }
44        System.out.println("all is over!");
45    }
46}
47
48

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
1package Synchronized.Seven.Phenomenon;
2
3public class Phenomenon7 implements Runnable{
4    static Phenomenon7 instence = new Phenomenon7();
5    //static修饰的背后'锁'是.class对象
6    public synchronized void Method1() {
7        System.out.println("I'm a synchronized and static method,my name is:"+Thread.currentThread().getName());
8        try {
9            Thread.sleep(3000);
10        } catch (InterruptedException e) {
11            e.printStackTrace();
12        }
13        throw new RuntimeException();
14        //System.out.println(Thread.currentThread().getName()+"is over!");
15    }
16    //没有静态修饰,'锁'是t实例本身his对象.
17    public synchronized void Method2() {
18        System.out.println("I'm a synchronized method ,my name is:"+Thread.currentThread().getName());
19        try {
20            Thread.sleep(3000);
21        } catch (InterruptedException e) {
22            e.printStackTrace();
23        }
24        System.out.println(Thread.currentThread().getName()+"is over!");
25    }
26    @Override
27    public void run() {
28        if(Thread.currentThread().getName().equals("Thread-0")){
29            Method1();
30        }else{
31            Method2();
32        }
33    }
34    public static void main(String [] args){
35        Thread t1 = new Thread(instence);
36        Thread t2 = new Thread(instence);
37        t1.start();
38        t2.start();
39        while(t1.isAlive()||t2.isAlive()){
40        }
41        System.out.println("all is over!");
42    }
43}
44
45

I’m a synchronized and static method,my name is:Thread-0
Exception in thread “Thread-0” I’m a synchronized method ,my name is:Thread-1
java.lang.RuntimeException at Synchronized.Seven.Phenomenon.Phenomenon7.Method1(Phenomenon7.java:13) at Synchronized.Seven.Phenomenon.Phenomenon7.run(Phenomenon7.java:29)
at java.lang.Thread.run(Thread.java:748)
Thread-1is over!
all is over!

结论:当方法中抛出了异常之后,JVM会帮助我们释放掉,synchronized获得的锁。以至于后序别的线程中的synchronized可以重新获取这把对象锁或类锁。

1.8、总结

1、一个锁只能同时被一个线程获取,没有拿到锁的线程必须等待。
2、每个实例都对应有自己的一把锁,不同实例之间互不影响;例如:当锁对象是 *.class 以及synchronized修饰的static方法的时候,所有的对象共用同一把类锁;
3、无论这个方法是正常执行完毕还是抛出了异常,都会释放掉自身持有的’锁’ ;

给TA打赏
共{{data.count}}人
人已打赏
安全经验

Google Adsense广告CPC(单元点击价格)为什么会减少??

2021-10-11 16:36:11

安全经验

安全咨询服务

2022-1-12 14:11:49

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索