Java多线程之synchronized

标签: java 多线程 synchronized | 发表时间:2012-03-22 16:43 | 作者:hopezhangbo
出处:http://blog.csdn.net

这里通过三个测试类阐述了synchronized应用的不同场景


首先是最基本的synchronized Method的使用

  1. package com.jadyer.thread.sync;  
  2.   
  3. /** 
  4.  * Synchronized Method Test 
  5.  * @see =================================================================================================== 
  6.  * @see 概述:Java中的每个对象都有一个锁(lock)或者叫做监视器(monitor) 
  7.  * @see 说明:当synchronized关键字修饰一个方法时,则该方法为同步方法 
  8.  * @see      当某个线程访问某个对象的synchronized方法时,则表示将该对象上锁 
  9.  * @see      此时其它的任何线程,均无法访问该对象中的任何一个synchronized方法(但允许访问该对象中的非synchronized方法) 
  10.  * @see      直到该线程所访问的synchronized方法执行完毕(或者抛出了异常)之后,该对象的锁才会被释放 
  11.  * @see      此时其它的任何线程,才被允许访问该synchronized方法,或者是该对象中的其它synchronized方法 
  12.  * @see =================================================================================================== 
  13.  * @see 总结:如果一个对象有多个synchronized方法,某一时刻某个线程已经执行了该对象中的某一个synchronized方法 
  14.  * @see      那么在该方法没有执行完毕之前,其它线程是无法访问该对象中的,包括该方法在内的,任何一个synchronized方法 
  15.  * @see      重点在于判断Synchronized锁的是谁。如果该方法是静态的,则锁Class对象,否则锁的就是当前对象 
  16.  * @see =================================================================================================== 
  17.  * @see 补充:1)这只是针对多个线程操作同一个类的同一个对象的情况。www.linuxidc.com若多个线程操作同一个类的不同对象,则不存在这种情况 
  18.  * @see      2)Java中的volatile变量也可以看作是一种"程度较轻的synchronized" 
  19.  * @see        关于volatile的更多信息,请参考http://www.ibm.com/developerworks/cn/java/j-jtp06197.html 
  20.  * @see 备注:实际项目中,用到的更多的还是JDK5.0开始推出的Java并发包,即java.util.concurrent包里面的工具类 
  21.  * @see      java.util.concurrent可以非常细粒度的实现并发。比如线程访问到了一个已被锁的对象,它可以让这个线程等到10秒 
  22.  * @see      10秒后如果该对象仍未被解锁,那么就可以返回给用户超时的提示等,而如果使用synchronized则是无法这么精确控制的 
  23.  * @see =================================================================================================== 
  24.  * @see 注意:1)当synchronized方法执行完或者发生异常时,会自动释放锁 
  25.  * @see      2)被synchronized保护的数据应该是private的,否则也就没必要去通过方法来访问这个public的数据了 
  26.  * @see =================================================================================================== 
  27.  * @author 宏宇 
  28.  * @create Feb 21, 2012 5:29:39 PM 
  29.  */  
  30. public  class SynchronizedTest {  
  31.      public  static  void main(String[] args) {  
  32.         Bank bank =  new Bank();  
  33.           
  34.         Thread tt11 =  new Thread( new ThreadRMB(bank));  
  35.           
  36.         //new一个新的Bank对象。此时存在两个Bank对象,并且它们属于同一个类的不同的对象   
  37.         //如要验证多个线程操作同一个类的不同的对象的synchronized方法,只需取消注释该行代码即可   
  38.         //bank = new Bank();   
  39.           
  40.         Thread tt22 =  new Thread( new ThreadDollar(bank));  
  41.           
  42.         tt11.start();  
  43.         tt22.start();  
  44.     }  
  45. }  
  46.   
  47.   
  48. class ThreadRMB  implements Runnable{  
  49.      private Bank bank;  
  50.      public ThreadRMB(Bank bank){  
  51.          this.bank = bank;  
  52.     }  
  53.     @Override  
  54.      public  void run() {  
  55.         bank.getRMB();  
  56.     }  
  57. }  
  58.   
  59.   
  60. class ThreadDollar  implements Runnable{  
  61.      private Bank bank;  
  62.      public ThreadDollar(Bank bank){  
  63.          this.bank = bank;  
  64.     }  
  65.     @Override  
  66.      public  void run() {  
  67.         bank.getDollar();  
  68.     }  
  69. }  
  70.   
  71.   
  72. class Bank{  
  73.      public  synchronized  void getRMB(){  
  74.          for( int i=0; i<20; i++){  
  75.              try {  
  76.                 Thread.sleep(( long)(Math.random()*1000));  
  77.             }  catch (InterruptedException e) {  
  78.                 e.printStackTrace();  
  79.             }  
  80.             System.out.println(Thread.currentThread().getName() + ":" + i);  
  81.         }  
  82.     }  
  83.       
  84.      public  synchronized  void getDollar(){  
  85.          for( int i=0; i<20; i++){  
  86.              try {  
  87.                 Thread.sleep(( long)(Math.random()*1000));  
  88.             }  catch (InterruptedException e) {  
  89.                 e.printStackTrace();  
  90.             }  
  91.             System.out.println(Thread.currentThread().getName() + ":" + i);  
  92.         }  
  93.     }  
  94. }  
下面演示的是synchronized static Method的使用
  1. package com.jadyer.thread.sync;  
  2.   
  3. /** 
  4.  * Synchronized Static Method Test 
  5.  * @see 说明:如果某个synchronized方法是static的 
  6.  * @see      那么当线程访问该方法时,它锁的并不是synchronized方法所在的对象,而是该方法所在的对象所对应的Class对象 
  7.  * @see      因为Java中无论一个类有多少个对象,这些对象都会对应唯一的一个Class对象 
  8.  * @see      因此当线程分别访问同一个类的两个对象的两个static的synchronized方法时,它们的执行顺序也是顺序执行的 
  9.  * @see      即一个线程先执行一个static的synchronized方法,执行完毕后,另一个线程才开始执行另一个static的synchronized方法 
  10.  * @see 总结:重点在于判断synchronized锁的是谁。www.linuxidc.com如果该方法是静态的,则锁Class对象,否则锁的就是当前对象 
  11.  * @author 宏宇 
  12.  * @create Feb 21, 2012 5:29:39 PM 
  13.  */  
  14. public  class SynchronizedStaticTest {  
  15.      public  static  void main(String[] args) {  
  16.         Bank bank =  new Bank();  
  17.           
  18.         Thread tt11 =  new Thread( new ThreadRMB(bank));  
  19.         Thread tt22 =  new Thread( new ThreadDollar(bank));  
  20.           
  21.         tt11.start();  
  22.         tt22.start();  
  23.     }  
  24. }  
  25.   
  26.   
  27. class ThreadRMB  implements Runnable{  
  28.      private Bank bank;  
  29.      public ThreadRMB(Bank bank){  
  30.          this.bank = bank;  
  31.     }  
  32.     @Override  
  33.      public  void run() {  
  34.         bank.getRMB();  
  35.     }  
  36. }  
  37.   
  38.   
  39. class ThreadDollar  implements Runnable{  
  40.      private Bank bank;  
  41.      public ThreadDollar(Bank bank){  
  42.          this.bank = bank;  
  43.     }  
  44.     @Override  
  45.      public  void run() {  
  46.         bank.getDollar();  
  47.     }  
  48. }  
  49.   
  50.   
  51. class Bank{  
  52.     //如要验证synchronized锁同一个类的对象,和锁它的Class对象的区别   
  53.     //可去掉static关键字,再查看控制台打印,即public synchronized void getRMB()   
  54.      public  synchronized  static  void getRMB(){  
  55.          for( int i=0; i<20; i++){  
  56.              try {  
  57.                 Thread.sleep(( long)(Math.random()*1000));  
  58.             }  catch (InterruptedException e) {  
  59.                 e.printStackTrace();  
  60.             }  
  61.             System.out.println(Thread.currentThread().getName() + ":" + i);  
  62.         }  
  63.     }  
  64.       
  65.      public  synchronized  static  void getDollar(){  
  66.          for( int i=0; i<20; i++){  
  67.              try {  
  68.                 Thread.sleep(( long)(Math.random()*1000));  
  69.             }  catch (InterruptedException e) {  
  70.                 e.printStackTrace();  
  71.             }  
  72.             System.out.println(Thread.currentThread().getName() + ":" + i);  
  73.         }  
  74.     }  
  75. }  
最后演示的是synchronized Block的使用
  1. package com.jadyer.thread.sync;  
  2.   
  3. /** 
  4.  * Synchronized Block Test 
  5.  * @author 宏宇 
  6.  * @create Feb 21, 2012 5:29:39 PM 
  7.  */  
  8. public  class SynchronizedBlockTest {  
  9.      public  static  void main(String[] args) {  
  10.         Bank bank =  new Bank();  
  11.           
  12.         Thread tt11 =  new Thread( new ThreadRMB(bank));  
  13.           
  14.         //如果要验证synchronized(this)锁的是当前类的对象,而非当前类的Class对象   
  15.         //则可取消注释该行代码,再观察控制台打印效果。效果应该是两个线程并发执行的输出   
  16.         //bank = new Bank();   
  17.           
  18.         Thread tt22 =  new Thread( new ThreadDollar(bank));  
  19.           
  20.         tt11.start();  
  21.         tt22.start();  
  22.     }  
  23. }  
  24.   
  25.   
  26. class ThreadRMB  implements Runnable{  
  27.      private Bank bank;  
  28.      public ThreadRMB(Bank bank){  
  29.          this.bank = bank;  
  30.     }  
  31.     @Override  
  32.      public  void run() {  
  33.         bank.getRMB();  
  34.     }  
  35. }  
  36.   
  37.   
  38. class ThreadDollar  implements Runnable{  
  39.      private Bank bank;  
  40.      public ThreadDollar(Bank bank){  
  41.          this.bank = bank;  
  42.     }  
  43.     @Override  
  44.      public  void run() {  
  45.         bank.getDollar();  
  46.     }  
  47. }  
  48.   
  49.   
  50. /** 
  51.  * Bank 
  52.  * @see 说明:synchronized块的写法:synchronized(object){//TODO...},它表示线程在执行的时候,会对object对象上锁 
  53.  * @see      通常会把java.lang.Object对象传进来,事实上这里可以传进来任何的对象 
  54.  * @see      因为它是一个没有实际作用的对象,其仅仅起到锁的作用,就像一个标识一样 
  55.  * @see 作用:它表示,如果线程能够进入到这里,即执行到这里,那么,就将object对象锁上 
  56.  * @see      如果另一个线程也执行到这里,发现object对象已上锁,则会等待其解锁后,才会去执行synchronized块里面的代码 
  57.  * @see 补充:synchronized(this)表示对当前类的对象上锁。注意,它锁的不是当前类的Class对象 
  58.  * @see      synchronized(Bank.class)表示对当前类的Class对象上锁 
  59.  * @author 宏宇 
  60.  * @create Feb 22, 2012 2:29:16 AM 
  61.  */  
  62. class Bank{  
  63.      private Object obj11 =  new Object();  
  64.      private Object obj22 =  new Object();  
  65.       
  66.      public  void getRMB(){  
  67.         //synchronized(obj11){   
  68.          synchronized (Bank. class) {  
  69.              for( int i=0; i<20; i++){  
  70.                  try {  
  71.                     Thread.sleep(( long)(Math.random()*1000));  
  72.                 }  catch (InterruptedException e) {  
  73.                     e.printStackTrace();  
  74.                 }  
  75.                 System.out.println(Thread.currentThread().getName() + ":" + i);  
  76.             }  
  77.         }  
  78.     }  
  79.       
  80.      public  void getDollar(){  
  81.         //synchronized(obj11){   
  82.         //synchronized(obj22){   
  83.          synchronized ( this) {  
  84.              for( int i=0; i<20; i++){  
  85.                  try {  
  86.                     Thread.sleep(( long)(Math.random()*1000));  
  87.                 }  catch (InterruptedException e) {  
  88.                     e.printStackTrace();  
  89.                 }  
  90.                 System.out.println(Thread.currentThread().getName() + ":" + i);  
  91.             }  
  92.         }  
  93.     }  
  94. }

作者:hopezhangbo 发表于2012-3-22 16:43:31 原文链接
阅读:1 评论:0 查看评论

相关 [java 多线程 synchronized] 推荐:

Java多线程之synchronized

- - CSDN博客推荐文章
这里通过三个测试类阐述了synchronized应用的不同场景. 首先是最基本的synchronized Method的使用.  * @see 概述:Java中的每个对象都有一个锁(lock)或者叫做监视器(monitor) .  * @see 说明:当synchronized关键字修饰一个方法时,则该方法为同步方法 .

[原]Java多线程中的synchronized、volatile和无锁编程

- - Snowball
新建状态(New):新创建了一个线程对象. 就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法. 该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权. 运行状态(Running):就绪状态的线程获取了CPU,执行程序代码. 阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行.

[转]java synchronized详解

- - 小彰
Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码.      一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行. 另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块.

文章: Java SE1.6中的Synchronized

- - InfoQ cn
在多线程并发编程中Synchronized一直是元老级角色,很多人都会称呼它为重量级锁,但是随着Java SE1.6对Synchronized进行了各种优化之后,有些情况下它并不那么重了,本文详细介绍了Java SE1.6中为了减少获得锁和释放锁带来的性能消耗,而引入的偏向锁和轻量级锁,以及锁的存储结构和升级过程.

Java同步块(Synchronized Blocks)

- - 并发编程网 - ifeve.com
原文链接  作者:Jakob Jenkov  译者:李同杰. Java 同步块(synchronized block)用来标记方法或者代码块是同步的. Java同步关键字(synchronzied). Java 同步关键字( synchronized ). Java中的同步块用synchronized标记.

java 并发编程 synchronized

- - Java - 编程语言 - ITeye博客
同步原语--synchronized. synchronized(class)很特别,它会让另一个线程在任何需要获取class做为monitor的地方等待.class与this做为不同的监视器可以同时使用,不存在一个线程获取了class,另一个线程就不能获取该class的一切实例.. ->线程各自获取monitor,不会有等待..

Java中Synchronized的用法

- - CSDN博客推荐文章
synchronized是Java中的关键字,是一种同步锁. 它修饰的对象有以下几种:. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;.

java-synchronized修饰方法释疑

- - ITeye博客
java里面用synchronized修饰方法时:. 对于 同一个对象的来说. 所有synchronized修饰的方法会 相互阻塞(即调用了某一个synchronized修饰的方法,则其余所有synchronized修饰的方法的调用都会阻塞,需要等待获取内置锁). 没有synchronized修饰的方法的则不会阻塞.

Java synchronized同步方法和同步块总结

- - 编程语言 - ITeye博客
今天做了一些实验,把Java synchronized同步方法和同步块总结一下,欢迎拍砖. Java synchronized同步方法和同步块总结:. synchronized method() {...} 锁对象的所有同步方法. 一个进程进入某对象同步方法后,其它线程不能同时访问这个对象中任何一个同步方法.

Java线程同步中关键字synchronized详述

- - 编程语言 - ITeye博客
synchronized关键可以修饰函数、函数内语句. 无论它加上方法还是对象上,它取得的锁都是对象,而不是把一段代码或是函数当作锁. 1,当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一段时间只能有一个线程得到执行,而另一个线程只有等当前线程执行完以后才能执行这块代码.