zoukankan      html  css  js  c++  java
  • java中synchronized 用在实例方法和对象方法上面的区别

    https://bijian1013.iteye.com/blog/1836575

     在Java中,synchronized 是用来表示同步的,我们可以synchronized 来修饰一个方法。也可以synchronized 来修饰方法里面的一个语句块。

          修饰实例方法:

    Java代码  收藏代码
    1. public synchronized void normalMethod() throws InterruptedException {  
    2.     for (int i = 0; i < 10; i++) {  
    3.         Thread.sleep(1000);  
    4.         System.out.println("normalMethod:" + i);  
    5.     }  
    6. }  

          修饰类方法(static 方法):

    Java代码  收藏代码
    1. public static synchronized void staticMethod() throws InterruptedException {  
    2.     for (int i = 0; i < 10; i++) {  
    3.         Thread.sleep(500);  
    4.         System.out.println("staticMethod:" + i);  
    5.     }  
    6. }  

           修饰方法里面语句块:

    Java代码  收藏代码
    1. public static void staticMethod() throws InterruptedException  {    
    2.         synchronized (locks) {    
    3.             for (int i = 0; i < 10; i++)  {    
    4.                 Thread.sleep(1000);    
    5.                 System.out.println("staticMethod:" + i);    
    6.            }    
    7.        }    
    8. }    

          注意:这里不能用synchronized修饰方法外面的语句块(我把他叫做类语句块),虽然我们可以在方法外面定义语句块,这样做会遇到编译错误,这里涉及到了Java里面的对象初始化的部分知识。大概的原因就是synchronized锁住的是对象,当初始化对象的时候,JVM在对象初始化完成之前会调用方法外面的语句块,这个时候对象还不存在,所以就不存在锁了。

          那么,在static方法和非static方法前面加synchronized到底有什么不同呢?

          static的方法属于类方法,它属于这个Class(注意:这里的Class不是指Class的某个具体对象),那么static获取到的锁,就是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。而非static方法获取到的锁,就是当前调用这个方法的对象的锁了。所以,他们之间不会产生互斥。

          实例1:

    Java代码  收藏代码
    1. package com.bijian.thread;  
    2.   
    3. public class SynchronizedTest {  
    4.   
    5.     public static synchronized void staticMethod() throws InterruptedException {  
    6.         for (int i = 0; i < 10; i++) {  
    7.             Thread.sleep(500);  
    8.             System.out.println("staticMethod:" + i);  
    9.         }  
    10.     }  
    11.   
    12.     public synchronized void normalMethod() throws InterruptedException {  
    13.         for (int i = 0; i < 10; i++) {  
    14.             Thread.sleep(1000);  
    15.             System.out.println("normalMethod:" + i);  
    16.         }  
    17.     }  
    18.   
    19.     public static void main(String[] args) {  
    20.         final SynchronizedTest synchronizedTest = new SynchronizedTest();  
    21.         Thread thread = new Thread(new Runnable() {  
    22.             public void run() {  
    23.                 try {  
    24.                     synchronizedTest.normalMethod();  
    25.                 } catch (InterruptedException e) {  
    26.                     e.printStackTrace();  
    27.                 }  
    28.             }  
    29.         }, "a");  
    30.   
    31.         Thread thread1 = new Thread(new Runnable() {  
    32.             public void run() {  
    33.                 try {  
    34.                     SynchronizedTest.staticMethod();  
    35.                 } catch (InterruptedException e) {  
    36.                     e.printStackTrace();  
    37.                 }  
    38.             }  
    39.         }, "b");  
    40.   
    41.         thread1.start();  
    42.         thread.start();  
    43.     }  
    44. }  

           运行结果:

    Text代码  收藏代码
    1. staticMethod:0  
    2. normalMethod:0  
    3. staticMethod:1  
    4. staticMethod:2  
    5. normalMethod:1  
    6. staticMethod:3  
    7. staticMethod:4  
    8. normalMethod:2  
    9. staticMethod:5  
    10. staticMethod:6  
    11. normalMethod:3  
    12. staticMethod:7  
    13. staticMethod:8  
    14. normalMethod:4  
    15. staticMethod:9  
    16. normalMethod:5  
    17. normalMethod:6  
    18. normalMethod:7  
    19. normalMethod:8  
    20. normalMethod:9  

           那当我们想让所有这个类下面的对象都同步的时候,也就是让所有这个类下面的对象共用同一把锁的时候,我们如何办呢?

           法1:将normalMethod方法也改成static,这样这两个static方法都属于类方法,它们获取到的锁都是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。但这样会影响代码结构和对象的封装性。

           修改实例1如下:

    Java代码  收藏代码
    1. package com.bijian.thread;  
    2.   
    3. public class SynchronizedTest {  
    4.     public static synchronized void staticMethod() throws InterruptedException {  
    5.         for (int i = 0; i < 10; i++) {  
    6.             Thread.sleep(500);  
    7.             System.out.println("staticMethod:" + i);  
    8.         }  
    9.     }  
    10.     public static synchronized void normalMethod() throws InterruptedException {  
    11.         for (int i = 0; i < 10; i++) {  
    12.             Thread.sleep(1000);  
    13.             System.out.println("normalMethod:" + i);  
    14.         }  
    15.     }  
    16.   
    17.     public static void main(String[] args) {  
    18.         Thread thread = new Thread(new Runnable() {  
    19.             public void run() {  
    20.                 try {  
    21.                     SynchronizedTest.normalMethod();  
    22.                 } catch (InterruptedException e) {  
    23.                     e.printStackTrace();  
    24.                 }  
    25.             }  
    26.         }, "a");  
    27.           
    28.         Thread thread1 = new Thread(new Runnable() {  
    29.             public void run() {  
    30.                 try {  
    31.                     SynchronizedTest.staticMethod();  
    32.                 } catch (InterruptedException e) {  
    33.                     e.printStackTrace();  
    34.                 }  
    35.             }  
    36.         }, "b");  
    37.   
    38.         thread1.start();  
    39.         thread.start();  
    40.     }  
    41. }  

           运行结果:

    Text代码  收藏代码
    1. staticMethod:0  
    2. staticMethod:1  
    3. staticMethod:2  
    4. staticMethod:3  
    5. staticMethod:4  
    6. staticMethod:5  
    7. staticMethod:6  
    8. staticMethod:7  
    9. staticMethod:8  
    10. staticMethod:9  
    11. normalMethod:0  
    12. normalMethod:1  
    13. normalMethod:2  
    14. normalMethod:3  
    15. normalMethod:4  
    16. normalMethod:5  
    17. normalMethod:6  
    18. normalMethod:7  
    19. normalMethod:8  
    20. normalMethod:9  

           也许有人说:将实例1的staticMethod方法改成的static去掉也能达到目的。确实可以,因为非static方法获取到的锁,就是当前调用这个方法的对象的锁,而实例1只有一个SynchronizedTest实例,如再创建一个实例,则就有问题了。如下所示:

             

    Java代码  收藏代码
    1. package com.bijian.thread;  
    2.   
    3. public class SynchronizedTest {  
    4.   
    5.     public synchronized void staticMethod() throws InterruptedException {  
    6.         for (int i = 0; i < 10; i++) {  
    7.             Thread.sleep(500);  
    8.             System.out.println("staticMethod:" + i);  
    9.         }  
    10.     }  
    11.   
    12.     public synchronized void normalMethod() throws InterruptedException {  
    13.         for (int i = 0; i < 10; i++) {  
    14.             Thread.sleep(1000);  
    15.             System.out.println("normalMethod:" + i);  
    16.         }  
    17.     }  
    18.   
    19.     public static void main(String[] args) {  
    20.         final SynchronizedTest synchronizedTest = new SynchronizedTest();  
    21.         Thread thread = new Thread(new Runnable() {  
    22.             public void run() {  
    23.                 try {  
    24.                     synchronizedTest.normalMethod();  
    25.                 } catch (InterruptedException e) {  
    26.                     e.printStackTrace();  
    27.                 }  
    28.             }  
    29.         }, "a");  
    30.   
    31.         //为了验证获取到的锁都是当前调用这个方法的对象所属的类,特另新建一个对象  
    32.         final SynchronizedTest synchronizedTest2 = new SynchronizedTest();  
    33.           
    34.         Thread thread1 = new Thread(new Runnable() {  
    35.             public void run() {  
    36.                 try {  
    37.                     synchronizedTest2.staticMethod();  
    38.                 } catch (InterruptedException e) {  
    39.                     e.printStackTrace();  
    40.                 }  
    41.             }  
    42.         }, "b");  
    43.   
    44.         thread1.start();  
    45.         thread.start();  
    46.     }  
    47. }  

           运行结果:

    Text代码  收藏代码
    1. staticMethod:0  
    2. staticMethod:1  
    3. normalMethod:0  
    4. staticMethod:2  
    5. staticMethod:3  
    6. normalMethod:1  
    7. staticMethod:4  
    8. staticMethod:5  
    9. normalMethod:2  
    10. staticMethod:6  
    11. normalMethod:3  
    12. staticMethod:7  
    13. staticMethod:8  
    14. normalMethod:4  
    15. staticMethod:9  
    16. normalMethod:5  
    17. normalMethod:6  
    18. normalMethod:7  
    19. normalMethod:8  
    20. normalMethod:9  

           法2:语句块锁,直接看如下实例:

           实例2:

    Java代码  收藏代码
    1. package com.bijian.thread;  
    2.   
    3. public class SynchronizedTest {  
    4.   
    5.     public final static Byte[] locks = new Byte[0];    
    6.   
    7.     public static void staticMethod() throws InterruptedException {  
    8.         synchronized(locks) {  
    9.             for (int i = 0; i < 10; i++) {  
    10.                 Thread.sleep(500);  
    11.                 System.out.println("staticMethod:" + i);  
    12.             }  
    13.         }  
    14.     }  
    15.   
    16.     public void normalMethod() throws InterruptedException {  
    17.         synchronized(locks) {  
    18.             for (int i = 0; i < 10; i++) {  
    19.                 Thread.sleep(1000);  
    20.                 System.out.println("normalMethod:" + i);  
    21.             }  
    22.         }  
    23.     }  
    24.   
    25.     public static void main(String[] args) {  
    26.         final SynchronizedTest synchronizedTest = new SynchronizedTest();  
    27.         Thread thread = new Thread(new Runnable() {  
    28.             public void run() {  
    29.                 try {  
    30.                     synchronizedTest.normalMethod();  
    31.                 } catch (InterruptedException e) {  
    32.                     e.printStackTrace();  
    33.                 }  
    34.             }  
    35.         }, "a");  
    36.   
    37.         Thread thread1 = new Thread(new Runnable() {  
    38.             public void run() {  
    39.                 try {  
    40.                     SynchronizedTest.staticMethod();  
    41.                 } catch (InterruptedException e) {  
    42.                     e.printStackTrace();  
    43.                 }  
    44.             }  
    45.         }, "b");  
    46.   
    47.         thread1.start();  
    48.         thread.start();  
    49.     }  
    50. }  

           运行结果:

    Text代码  收藏代码
    1. staticMethod:0  
    2. staticMethod:1  
    3. staticMethod:2  
    4. staticMethod:3  
    5. staticMethod:4  
    6. staticMethod:5  
    7. staticMethod:6  
    8. staticMethod:7  
    9. staticMethod:8  
    10. staticMethod:9  
    11. normalMethod:0  
    12. normalMethod:1  
    13. normalMethod:2  
    14. normalMethod:3  
    15. normalMethod:4  
    16. normalMethod:5  
    17. normalMethod:6  
    18. normalMethod:7  
    19. normalMethod:8  
    20. normalMethod:9  
  • 相关阅读:
    select中添加、修改、删除option元素
    asp之ajax技术:responstext中文乱码
    JAVA中的AJAX技术
    asp之IIS服务器:Windows2003 IIS6服务器上传文件不能超过200k解决方案
    ghost系统安装盘与普通安装盘有何区别?
    简单破解忘记Windows密码的解决方法
    删除用户账户密码
    asp数据库 rs.open语句详解
    asp函数 生成随机数
    microsoft Report view项目部署出错
  • 原文地址:https://www.cnblogs.com/mkl34367803/p/10083298.html
Copyright © 2011-2022 走看看