zoukankan      html  css  js  c++  java
  • 架构师养成记--3.synchronized细节问题

    一、synchronized有锁重入的特点,某个线程得到对象的锁后,再次请求此对象可以再次得到改对象的锁。如下示例,在method1中调用method2,在method2中调用method3,而method1、method2和method3都是加了synchronized关键字的。

     1 /**
     2  * synchronized的重入
     3  * @author alienware
     4  *
     5  */
     6 public class SyncDubbo1 {
     7 
     8     public synchronized void method1(){
     9         System.out.println("method1..");
    10         method2();
    11     }
    12     public synchronized void method2(){
    13         System.out.println("method2..");
    14         method3();
    15     }
    16     public synchronized void method3(){
    17         System.out.println("method3..");
    18     }
    19     
    20     public static void main(String[] args) {
    21         final SyncDubbo1 sd = new SyncDubbo1();
    22         Thread t1 = new Thread(new Runnable() {
    23             @Override
    24             public void run() {
    25                 sd.method1();
    26             }
    27         });
    28         t1.start();
    29     }
    30 }

    二、父类和子类的方法都是synchronized的,在子类的方法中调用父类的方法,也是线程安全的。

     1 /**
     2  * synchronized的重入
     3  * @author alienware
     4  *
     5  */
     6 public class SyncDubbo2 {
     7 
     8     static class Main {
     9         public int i = 10;
    10         public synchronized void operationSup(){
    11             try {
    12                 i--;
    13                 System.out.println("Main print i = " + i);
    14                 Thread.sleep(100);
    15             } catch (InterruptedException e) {
    16                 e.printStackTrace();
    17             }
    18         }
    19     }
    20     
    21     static class Sub extends Main {
    22         public synchronized void operationSub(){
    23             try {
    24                 while(i > 0) {
    25                     i--;
    26                     System.out.println("Sub print i = " + i);
    27                     Thread.sleep(100);        
    28                     this.operationSup();
    29                 }
    30             } catch (InterruptedException e) {
    31                 e.printStackTrace();
    32             }
    33         }
    34     }
    35     
    36     public static void main(String[] args) {
    37         
    38         Thread t1 = new Thread(new Runnable() {
    39             @Override
    40             public void run() {
    41                 Sub sub = new Sub();
    42                 sub.operationSub();
    43             }
    44         });
    45         
    46         t1.start();
    47     }
    48     
    49     
    50 }

    执行结果:

     

    三、synchronized方法内抛异常怎么处理

      throw RuntimeException打断此线程或者记录日志然后continue,选择哪种方案取决于具体业务要求。

     1 /**
     2  * synchronized异常
     3  * @author alienware
     4  *
     5  */
     6 public class SyncException {
     7 
     8     private int i = 0;
     9     public synchronized void operation(){
    10         while(true){
    11             try {
    12                 i++;
    13                 Thread.sleep(100);
    14                 System.out.println(Thread.currentThread().getName() + " , i = " + i);
    15                 if(i == 20){
    16                     //Integer.parseInt("a");
    17                     throw new RuntimeException();
    18                 }
    19             } catch (InterruptedException e) {
    20                 e.printStackTrace();
    21             }
    22         }
    23     }
    24     
    25     public static void main(String[] args) {
    26         
    27         final SyncException se = new SyncException();
    28         Thread t1 = new Thread(new Runnable() {
    29             @Override
    30             public void run() {
    31                 se.operation();
    32             }
    33         },"t1");
    34         t1.start();
    35     }
    36     
    37     
    38 }

     四、synchronized代码块锁,实用起来也会比较灵活

      this、class、Object都可以用来作为代码块锁

     1 /**
     2  * 使用synchronized代码块加锁,比较灵活
     3  * @author alienware
     4  *
     5  */
     6 public class ObjectLock {
     7 
     8     public void method1(){
     9         synchronized (this) {    //对象锁
    10             try {
    11                 System.out.println("do method1..");
    12                 Thread.sleep(2000);
    13             } catch (InterruptedException e) {
    14                 e.printStackTrace();
    15             }
    16         }
    17     }
    18     
    19     public void method2(){        //类锁
    20         synchronized (ObjectLock.class) {
    21             try {
    22                 System.out.println("do method2..");
    23                 Thread.sleep(2000);
    24             } catch (InterruptedException e) {
    25                 e.printStackTrace();
    26             }
    27         }
    28     }
    29     
    30     private Object lock = new Object();
    31     public void method3(){        //任何对象锁
    32         synchronized (lock) {
    33             try {
    34                 System.out.println("do method3..");
    35                 Thread.sleep(2000);
    36             } catch (InterruptedException e) {
    37                 e.printStackTrace();
    38             }
    39         }
    40     }
    41     
    42     
    43     public static void main(String[] args) {
    44         
    45         final ObjectLock objLock = new ObjectLock();
    46         Thread t1 = new Thread(new Runnable() {
    47             @Override
    48             public void run() {
    49                 objLock.method1();
    50             }
    51         });
    52         Thread t2 = new Thread(new Runnable() {
    53             @Override
    54             public void run() {
    55                 objLock.method2();
    56             }
    57         });
    58         Thread t3 = new Thread(new Runnable() {
    59             @Override
    60             public void run() {
    61                 objLock.method3();
    62             }
    63         });
    64         
    65         t1.start();
    66         t2.start();
    67         t3.start();
    68         
    69         
    70     }
    71     
    72 }
    View Code

    五、尽量不要用String常量作为锁

    如下代码只会有t1线程运行,但可以new一个String对象。

     1 /**
     2  * synchronized代码块对字符串的锁,注意String常量池的缓存功能
     3  * @author alienware
     4  *
     5  */
     6 public class StringLock {
     7 
     8     public void method() {
     9         //new String("字符串常量")
    10         synchronized ("字符串常量") {
    11             try {
    12                 while(true){
    13                     System.out.println("当前线程 : "  + Thread.currentThread().getName() + "开始");
    14                     Thread.sleep(1000);        
    15                     System.out.println("当前线程 : "  + Thread.currentThread().getName() + "结束");
    16                 }
    17             } catch (InterruptedException e) {
    18                 e.printStackTrace();
    19             }
    20         }
    21     }
    22     
    23     public static void main(String[] args) {
    24         final StringLock stringLock = new StringLock();
    25         Thread t1 = new Thread(new Runnable() {
    26             @Override
    27             public void run() {
    28                 stringLock.method();
    29             }
    30         },"t1");
    31         Thread t2 = new Thread(new Runnable() {
    32             @Override
    33             public void run() {
    34                 stringLock.method();
    35             }
    36         },"t2");
    37         
    38         t1.start();
    39         t2.start();
    40     }
    41 }
    View Code

    六、一个对象被用作锁时,这个对象内的属性发生变化不会影响锁的使用。

     1 /**
     2  * 同一对象属性的修改不会影响锁的情况
     3  * @author alienware
     4  *
     5  */
     6 public class ModifyLock {
     7     
     8     private String name ;
     9     private int age ;
    10     
    11     public String getName() {
    12         return name;
    13     }
    14     public void setName(String name) {
    15         this.name = name;
    16     }
    17     public int getAge() {
    18         return age;
    19     }
    20     public void setAge(int age) {
    21         this.age = age;
    22     }
    23     
    24     public synchronized void changeAttributte(String name, int age) {
    25         try {
    26             System.out.println("当前线程 : "  + Thread.currentThread().getName() + " 开始");
    27             this.setName(name);
    28             this.setAge(age);
    29             
    30             System.out.println("当前线程 : "  + Thread.currentThread().getName() + " 修改对象内容为: " 
    31                     + this.getName() + ", " + this.getAge());
    32             
    33             Thread.sleep(2000);
    34             System.out.println("当前线程 : "  + Thread.currentThread().getName() + " 结束");
    35         } catch (InterruptedException e) {
    36             e.printStackTrace();
    37         }
    38     }
    39     
    40     public static void main(String[] args) {
    41         final ModifyLock modifyLock = new ModifyLock();
    42         Thread t1 = new Thread(new Runnable() {
    43             @Override
    44             public void run() {
    45                 modifyLock.changeAttributte("张三", 20);
    46             }
    47         },"t1");
    48         Thread t2 = new Thread(new Runnable() {
    49             @Override
    50             public void run() {
    51                 modifyLock.changeAttributte("李四", 21);
    52             }
    53         },"t2");
    54         
    55         t1.start();
    56         try {
    57             Thread.sleep(100);
    58         } catch (InterruptedException e) {
    59             e.printStackTrace();
    60         }
    61         t2.start();
    62     }
    63     
    64 }
    View Code
  • 相关阅读:
    jquery 实现 html5 placeholder 兼容password密码框
    php返回json的结果
    使用PHP读取远程文件
    Sharepoint 自定义字段
    Sharepoint 中新增 aspx页面,并在页面中新增web part
    【转】Sharepoint 2010 配置我的站点及BLOG
    JS 实现 Div 向上浮动
    UserProfile同步配置
    【转】Import User Profile Photos from Active Directory into SharePoint 2010
    Sharepoint 2010 SP1升级后 FIMSynchronizationService 服务无法开启
  • 原文地址:https://www.cnblogs.com/sigm/p/6124079.html
Copyright © 2011-2022 走看看