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、无论这个方法是正常执行完毕还是抛出了异常,都会释放掉自身持有的’锁’ ;