2.synchronized

本文详细解析了Java中的synchronized关键字在不同场景下的应用,包括对象锁、类锁、重入锁特性及异常释放锁机制,并通过实例展示了多线程环境下如何避免竞态条件与死锁。
  1. synchronized关键字synchronized取得的锁都是对象锁,而不是把一段代码(方法)当做锁,所以代码中哪个线程先执行synchronized关键字的方法,哪个线程就持有该方法所属对象的锁(Lock)
  2. public class MultiThread {
  3.  
  4.    private  int num = 0;
  5.   
  6.    /** static */
  7.    public  synchronized void printNum(String tag){
  8.       try {
  9.         
  10.          if(tag.equals("a")){
  11.             num = 100;
  12.             System.out.println("tag a, set num over!");
  13.             Thread.sleep(1000);
  14.          } else {
  15.             num = 200;
  16.             System.out.println("tag b, set num over!");
  17.          }
  18.         
  19.          System.out.println("tag " + tag + ", num = " + num);
  20.         
  21.       } catch (InterruptedException e) {
  22.          e.printStackTrace();
  23.       }
  24.    }
  25.   
  26.    //注意观察run方法输出顺序
  27.    public static void main(String[] args) {
  28.      
  29.       //俩个不同的对象
  30.       final MultiThread m1 = new MultiThread();
  31.       final MultiThread m2 = new MultiThread();
  32.      
  33.       Thread t1 = new Thread(new Runnable() {
  34.          @Override
  35.          public void run() {
  36.             m1.printNum("a");
  37.          }
  38.       });
  39.      
  40.       Thread t2 = new Thread(new Runnable() {
  41.          @Override
  42.          public void run() {
  43.             m2.printNum("b");
  44.          }
  45.       });
  46.         
  47.       t1.start();
  48.       t2.start();
  49.      
  50.    }
  51.      
  52. }
  53. 输出结果:
  54. tag b, set num over!
  55. tag a, set num over!
  56. tag b, num = 200
  57. tag a, num = 100
  58.  
  59.  
  60. 在静态方法上加synchronized关键字,表示锁定.class类,类一级别的锁(独占.class类)。
  61. public class MultiThread {
  62.  
  63.    private static int num = 0;
  64.   
  65.    /** static */
  66.    在方法上加了static
  67.    public static synchronized void printNum(String tag){
  68.       try {
  69.         
  70.          if(tag.equals("a")){
  71.             num = 100;
  72.             System.out.println("tag a, set num over!");
  73.             Thread.sleep(1000);
  74.          } else {
  75.             num = 200;
  76.             System.out.println("tag b, set num over!");
  77.          }
  78.         
  79.          System.out.println("tag " + tag + ", num = " + num);
  80.         
  81.       } catch (InterruptedException e) {
  82.          e.printStackTrace();
  83.       }
  84.    }
  85.   
  86.    //注意观察run方法输出顺序
  87.    public static void main(String[] args) {
  88.      
  89.       //俩个不同的对象
  90.       final MultiThread m1 = new MultiThread();
  91.       final MultiThread m2 = new MultiThread();
  92.      
  93.       Thread t1 = new Thread(new Runnable() {
  94.          @Override
  95.          public void run() {
  96.             m1.printNum("a");
  97.          }
  98.       });
  99.      
  100.       Thread t2 = new Thread(new Runnable() {
  101.          @Override
  102.          public void run() {
  103.             m2.printNum("b");
  104.          }
  105.       });
  106.         
  107.       t1.start();
  108.       t2.start();
  109.      
  110.    }
  111.      
  112. }
  113. 输出结果:
  114.  
  115. tag a, set num over!
  116. tag a, num = 100
  117. tag b, set num over!
  118. tag b, num = 200
  119. 关键字synchronized拥有锁重入的功能,在使用synchronized时,当一个线程的到一个对象锁以后,再次请求此对象是可以再次得到该对象的锁。
  120. public class SyncDubbo1 {
  121.  
  122.    public synchronized void method1(){
  123.       System.out.println("method1..");
  124.       method2();
  125.    }
  126.    public synchronized void method2(){
  127.       System.out.println("method2..");
  128.       method3();
  129.    }
  130.    public synchronized void method3(){
  131.       System.out.println("method3..");
  132.    }
  133.   
  134.    public static void main(String[] args) {
  135.       final SyncDubbo1 sd = new SyncDubbo1();
  136.       Thread t1 = new Thread(new Runnable() {
  137.          @Override
  138.          public void run() {
  139.             sd.method1();
  140.          }
  141.       });
  142.       t1.start();
  143.    }
  144. }
  145. 输出结果:
  146. method1..
  147. method2..
  148. method3..
  149.  
  150.  
  151. public class SyncDubbo2 {
  152.  
  153.    static class Main {
  154.       public int i = 10;
  155.       public  synchronized void operationSup(){
  156.          try {
  157.             i--;
  158.             System.out.println("Main print i = " + i);
  159.             Thread.sleep(100);
  160.          } catch (InterruptedException e) {
  161.             e.printStackTrace();
  162.          }
  163.       }
  164.    }
  165.   
  166.    static class Sub extends Main {
  167.       public   synchronized void operationSub(){
  168.          try {
  169.             while(i > 0) {
  170.                 i--;
  171.                 System.out.println("Sub print i = " + i);
  172.                 Thread.sleep(100);   
  173.                 this.operationSup();
  174.             }
  175.          } catch (InterruptedException e) {
  176.             e.printStackTrace();
  177.          }
  178.       }
  179.    }
  180.   
  181.    public static void main(String[] args) {
  182.      
  183.       Thread t1 = new Thread(new Runnable() {
  184.          @Override
  185.          public void run() {
  186.             Sub sub = new Sub();
  187.             sub.operationSub();
  188.          }
  189.       });
  190.      
  191.       t1.start();
  192.    }
  193.   
  194.   
  195. }
  196. 输出结果:
  197. Sub print i = 9
  198. Main print i = 8
  199. Sub print i = 7
  200. Main print i = 6
  201. Sub print i = 5
  202. Main print i = 4
  203. Sub print i = 3
  204. Main print i = 2
  205. Sub print i = 1
  206. Main print i = 0
  207.  
  208. 出现异常,锁会自动释放
  209. public class SyncException {
  210.  
  211.    private int i = 0;
  212.    public synchronized void operation(){
  213.       while(true){
  214.          try {
  215.             i++;
  216.             Thread.sleep(100);
  217.             System.out.println(Thread.currentThread().getName() + " , i = " + i);
  218.             if(i == 8){
  219.             异常释放锁
  220.             throw new RuntimeException();
  221.             }
  222.          } catch (InterruptedException e) {
  223.             e.printStackTrace();
  224.          }
  225.       }
  226.    }
  227.   
  228.    public static void main(String[] args) {
  229.      
  230.       final SyncException se = new SyncException();
  231.       Thread t1 = new Thread(new Runnable() {
  232.          @Override
  233.          public void run() {
  234.             se.operation();
  235.          }
  236.       },"t1");
  237.       t1.start();
  238.    }
  239.   
  240.   
  241. }
  242.  
  243. 输出结果:
  244. t1 , i = 1
  245. t1 , i = 2
  246. t1 , i = 3
  247. t1 , i = 4
  248. t1 , i = 5
  249. t1 , i = 6
  250. t1 , i = 7
  251. t1 , i = 8
  252. Exception in thread "t1" java.lang.RuntimeException
  253.    at com.bjsxt.base.sync005.SyncException.operation(SyncException.java:18)
  254.    at com.bjsxt.base.sync005.SyncException$1.run(SyncException.java:32)
  255.    at java.lang.Thread.run(Thread.java:745)
  256.  
  257. 对于web应用程序,异常释放锁,如果不及时处理,很可能对应用程序业务逻辑产生严重的错误,比如现在执行一个队列任务,很多对象都在等待第一个对象正确执行完毕后再去释放锁,但是由于第一个对象出现异常导致业务逻辑没有正常执行完毕,就释放了锁,那么可想而知后续对象执行的都是错误的。所以这一点一定要注意。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值