Java关于Synchronized关键字在不同位置使用的理解

来源:互联网 发布:微信一键群发自动软件 编辑:程序博客网 时间:2024/05/22 20:05

Java中的Synchronized关键字

可以用来修饰同步方法:

像这样synchronized void f() {/*body*/}

也可以修饰同步语句块:

像这样synchronized(object){/*body*/}。

其中修饰同步方法还可以分为修饰static方法和实例方法。

其中修饰同步语句块还可以分为修饰instance变量,Object Reference对象引用,class 字面常量。

当synchronized作用在方法上时,锁住的便是对象实例(this);

所以synchronized void f() {/*body*/}和 void f(synchronized(this){/*body*/})是等价的。

当作用在静态方法时锁住的便是对象对应的Class实例,因为Class数据存在于永久带,因此静态方法锁相当于该类的一个全局锁;

当synchronized作用于某一个对象实例时,锁住的便是对应的代码块。

在HotSpot JVM实现中,锁有个专门的名字:对象监视器。


synchronized(class)
synchronized(this)
->线程各自获取monitor,不会有等待.

线程分别获取class和this,不会造成等待的例子:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.hyy.test;  
  2.   
  3. import java.util.concurrent.ExecutorService;  
  4. import java.util.concurrent.Executors;  
  5.   
  6. public class SyncTest02 implements Runnable {  
  7.   
  8.     private static boolean flag = true;  
  9.   
  10.     private void testSync1() {  
  11.         synchronized (this) {  
  12.             for (int i = 0; i < 100; i++) {  
  13.                 System.out.println("testSyncObject: " + i);  
  14.             }  
  15.         }  
  16.     }  
  17.   
  18.     private void testSync2() {  
  19.         synchronized (SyncTest02.class) {  
  20.             for (int i = 0; i < 100; i++) {  
  21.                 System.out.println("testSyncClass:" + i);  
  22.             }  
  23.         }  
  24.     }  
  25.   
  26.     @Override  
  27.     public void run() {  
  28.         // TODO Auto-generated method stub  
  29.   
  30.         if (flag) {  
  31.             flag = false;  
  32.             testSync1();  
  33.         } else {  
  34.             flag = true;  
  35.             testSync2();  
  36.         }  
  37.   
  38.     }  
  39.   
  40.     public static void main(String[] args) {  
  41.         ExecutorService exec = Executors.newFixedThreadPool(2);  
  42.         SyncTest02 sy1 = new SyncTest02();  
  43.         SyncTest02 sy2 = new SyncTest02();  
  44.   
  45.         exec.execute(sy1);  
  46.         exec.execute(sy2);  
  47.         exec.shutdown();  
  48.     }  
  49.   
  50. }  


synchronized(this)
synchronized(this)
->如果不同线程监视同一个实例对象,就会等待,如果不同的实例,不会等待.

不同线程监视同一个实例对象的例子

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.hyy.test;  
  2.   
  3. import java.util.concurrent.ExecutorService;  
  4. import java.util.concurrent.Executors;  
  5.   
  6. public class SyncTest {  
  7.   
  8.     public static void main(String[] args) {  
  9.         ExecutorService es = Executors.newFixedThreadPool(2);  
  10.         MyCount mc = new MyCount();  
  11.         MyThread mt1 = new MyThread(mc, "thread 1");  
  12.         MyThread mt2 = new MyThread(mc, "thread 2");  
  13.         es.execute(mt1);  
  14.         es.execute(mt2);  
  15.         es.shutdown();  
  16.     }  
  17.   
  18. }  
  19.   
  20. class MyThread extends Thread {  
  21.   
  22.     MyCount count;  
  23.     String threadName;  
  24.   
  25.     public MyThread(MyCount count, String threadName) {  
  26.         // TODO Auto-generated constructor stub  
  27.         this.count = count;  
  28.         this.threadName = threadName;  
  29.     }  
  30.   
  31.     @Override  
  32.     public void run() {  
  33.         // TODO Auto-generated method stub  
  34.         for (int i = 0; i < 10; i++) {  
  35.             count.addOne(threadName);  
  36.   
  37.             try {  
  38.                 sleep(100L);  
  39.             } catch (InterruptedException e) {  
  40.                 // TODO Auto-generated catch block  
  41.                 e.printStackTrace();  
  42.             }  
  43.         }  
  44.     }  
  45.   
  46. }  
  47.   
  48. class MyCount {  
  49.     int i;  
  50.   
  51.     public void addOne(String threadName) {  
  52.         synchronized (this) {  
  53.             i++;  
  54.             System.out.println(threadName + ":" + i);  
  55.         }  
  56.   
  57.     }  
  58. }  

输出为

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. thread 1:1  
  2. thread 2:2  
  3. thread 1:3  
  4. thread 2:4  
  5. thread 2:5  
  6. thread 1:6  
  7. thread 2:7  
  8. thread 1:8  
  9. thread 1:9  
  10. thread 2:10  
  11. thread 1:11  
  12. thread 2:12  
  13. thread 2:13  
  14. thread 1:14  
  15. thread 1:15  
  16. thread 2:16  
  17. thread 1:17  
  18. thread 2:18  
  19. thread 1:19  
  20. thread 2:20  

从输出上看,线程间出现了等待


不同线程监视不同实例对象的例子:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.hyy.test;  
  2.   
  3. import java.util.concurrent.ExecutorService;  
  4. import java.util.concurrent.Executors;  
  5.   
  6. public class SyncTest {  
  7.   
  8.     public static void main(String[] args) {  
  9.         ExecutorService es = Executors.newFixedThreadPool(2);  
  10.         MyCount mc = new MyCount("countONE");  
  11.         MyCount mc2 = new MyCount("countTWO");  
  12.         MyThread mt1 = new MyThread(mc, "thread 1");  
  13.         MyThread mt2 = new MyThread(mc2, "thread 2");  
  14.         es.execute(mt1);  
  15.         es.execute(mt2);  
  16.         es.shutdown();  
  17.     }  
  18.   
  19. }  
  20.   
  21. class MyThread extends Thread {  
  22.   
  23.     MyCount count;  
  24.     String threadName;  
  25.   
  26.     public MyThread(MyCount count, String threadName) {  
  27.         // TODO Auto-generated constructor stub  
  28.         this.count = count;  
  29.         this.threadName = threadName;  
  30.     }  
  31.   
  32.     @Override  
  33.     public void run() {  
  34.         // TODO Auto-generated method stub  
  35.         for (int i = 0; i < 10; i++) {  
  36.             count.addOne(threadName);  
  37.   
  38.             try {  
  39.                 sleep(100L);  
  40.             } catch (InterruptedException e) {  
  41.                 // TODO Auto-generated catch block  
  42.                 e.printStackTrace();  
  43.             }  
  44.         }  
  45.     }  
  46.   
  47. }  
  48.   
  49. class MyCount {  
  50.       
  51.     int i;  
  52.     String countName;  
  53.       
  54.       
  55.     public MyCount(String countName) {  
  56.         // TODO Auto-generated constructor stub  
  57.         this.countName = countName;  
  58.     }  
  59.       
  60.   
  61.     public void addOne(String threadName) {  
  62.         synchronized (this) {  
  63.             i++;  
  64.             System.out.println(threadName +"&&"+countName+ ":" + i);  
  65.         }  
  66.   
  67.     }  
  68. }  

输出为

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. thread 2&&countTWO:1  
  2. thread 1&&countONE:1  
  3. thread 2&&countTWO:2  
  4. thread 1&&countONE:2  
  5. thread 2&&countTWO:3  
  6. thread 1&&countONE:3  
  7. thread 2&&countTWO:4  
  8. thread 1&&countONE:4  
  9. thread 1&&countONE:5  
  10. thread 2&&countTWO:5  
  11. thread 2&&countTWO:6  
  12. thread 1&&countONE:6  
  13. thread 2&&countTWO:7  
  14. thread 1&&countONE:7  
  15. thread 1&&countONE:8  
  16. thread 2&&countTWO:8  
  17. thread 2&&countTWO:9  
  18. thread 1&&countONE:9  
  19. thread 1&&countONE:10  
  20. thread 2&&countTWO:10  

从输出上看,线程间没有发上等待。



synchronized(class)
synchronized(class)
->如果不同线程监视同一个实例或者不同的实例对象,都会等待.

不同线程监视不同实例对象的例子:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.hyy.test;  
  2.   
  3. import java.util.concurrent.ExecutorService;  
  4. import java.util.concurrent.Executors;  
  5.   
  6. public class SyncTest02 implements Runnable {  
  7.   
  8.     private static boolean flag = true;  
  9.   
  10.     private void testSync1() {  
  11.         synchronized (SyncTest02.class) {  
  12.             for (int i = 0; i < 100; i++) {  
  13.                 System.out.println("testSyncObject: " + i);  
  14.             }  
  15.         }  
  16.     }  
  17.   
  18.     private void testSync2() {  
  19.         synchronized (SyncTest02.class) {  
  20.             for (int i = 0; i < 100; i++) {  
  21.                 System.out.println("testSyncClass:" + i);  
  22.                   
  23.             }  
  24.         }  
  25.     }  
  26.   
  27.     @Override  
  28.     public void run() {  
  29.         // TODO Auto-generated method stub  
  30.   
  31.         if (flag) {  
  32.             flag = false;  
  33.             testSync1();  
  34.         } else {  
  35.             flag = true;  
  36.             testSync2();  
  37.         }  
  38.   
  39.     }  
  40.   
  41.     public static void main(String[] args) {  
  42.         ExecutorService exec = Executors.newFixedThreadPool(2);  
  43.         SyncTest02 sy1 = new SyncTest02();  
  44.         SyncTest02 sy2 = new SyncTest02();  
  45.   
  46.         exec.execute(sy1);  
  47.         exec.execute(sy2);  
  48.         exec.shutdown();  
  49.     }  
  50.   
  51. }  



0 0