Java提供了强制原子性的内部锁机制:synchronized块。但是内部锁是可重入的,当线程试图获得它自己占有的锁时,请求会成功。
简单的说,就是在一个synchronized方法内部调用本类的其他synchronized方法时,永远可以拿到锁。
如例子1.1所示
- public class LoggingWidget extends Widget{
- public static void main(String[] args) {
- LoggingWidget lw=new LoggingWidget();
- lw.doSomething();
- }
- public synchronized void doSomething(){
- System.out.println("LoggingWidget->doSomething()");
- doAnotherThing(); //调用自己类中其他的synchronized方法
- super.doSomething(); //调用父类的synchronized方法
- }
- private synchronized void doAnotherThing(){
- System.out.println("LoggingWidget->doAnotherThing()");
- }
- }
- class Widget{
- public synchronized void doSomething(){
- System.out.println("Widget->doSomething()");
- }
- }
执行结果是:
- LoggingWidget->doSomething()
- LoggingWidget->doAnotherThing()
- Widget->doSomething()
- public class reentry{
- int i=0;
- public static void main(String[] args) {
- reentry lw=new reentry();
- lw.doSomething();
- }
- public synchronized void doSomething(){
- System.out.println("doSomething()"+i++);
- doSomething(); //synchronized方法递归调用
- }
- }
- .....
- doSomething()3831
- doSomething()3832
- doSomething()3833
- Exception in thread "main" java.lang.StackOverflowError
- ......
- public class LoggingWidget {
- static public int i=0;
- public int ii=0;
- public LoggingWidget() {
- super();
- }
- public static void main(String[] args) {
- int totalNumOfThread=20; //有20个线程同时执行
- LoggingWidget lw=new LoggingWidget(); //每个线程都关联同一个LoggingWidget对象
- ArrayList<outer> o=new ArrayList<outer>();
- for(int s=0;s<totalNumOfThread;s++) //为20个线程赋值同一个LoggingWidget对象的引用
- {
- outer t=new outer();
- t.lw=lw;
- o.add(t);
- }
- for(int s=0;s<totalNumOfThread;s++)
- {
- new Thread((outer)o.get(s)).start(); //启动20个线程
- }
- }
- public void doSomething(){ //注意,这里没有给方法synchronized属性
- int sleep=(int)(Math.random()*500); //随机产生一个睡眠时间
- try {
- Thread.sleep(sleep); //睡眠
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- ii=i++; //为每个线程赋予一个ID,ID自增
- try {
- Thread.sleep(sleep); //继续睡眠
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(ii+"线程执行LoggingWidget->doSomething(),睡眠时间:"+sleep);
- }
- }
- class outer extends Thread
- {
- public LoggingWidget lw;
- public outer() {
- super();
- }
- @Override
- public void run() {
- lw.doSomething();
- super.run();
- }
- }
由于没有给方法synchronized属性,所以输出结果如下:
1线程执行LoggingWidget->doSomething(),睡眠时间:41线程执行LoggingWidget->doSomething(),睡眠时间:43线程执行LoggingWidget->doSomething(),睡眠时间:568线程执行LoggingWidget->doSomething(),睡眠时间:10811线程执行LoggingWidget->doSomething(),睡眠时间:15111线程执行LoggingWidget->doSomething(),睡眠时间:15712线程执行LoggingWidget->doSomething(),睡眠时间:17713线程执行LoggingWidget->doSomething(),睡眠时间:19214线程执行LoggingWidget->doSomething(),睡眠时间:21316线程执行LoggingWidget->doSomething(),睡眠时间:21817线程执行LoggingWidget->doSomething(),睡眠时间:23219线程执行LoggingWidget->doSomething(),睡眠时间:28019线程执行LoggingWidget->doSomething(),睡眠时间:35419线程执行LoggingWidget->doSomething(),睡眠时间:35819线程执行LoggingWidget->doSomething(),睡眠时间:40119线程执行LoggingWidget->doSomething(),睡眠时间:42819线程执行LoggingWidget->doSomething(),睡眠时间:43719线程执行LoggingWidget->doSomething(),睡眠时间:45519线程执行LoggingWidget->doSomething(),睡眠时间:46819线程执行LoggingWidget->doSomething(),睡眠时间:498如果方法public void doSomething()改成public synchronized void doSomething(),那么输出结果为:0线程执行LoggingWidget->doSomething(),睡眠时间:3841线程执行LoggingWidget->doSomething(),睡眠时间:262线程执行LoggingWidget->doSomething(),睡眠时间:3913线程执行LoggingWidget->doSomething(),睡眠时间:2894线程执行LoggingWidget->doSomething(),睡眠时间:2665线程执行LoggingWidget->doSomething(),睡眠时间:2486线程执行LoggingWidget->doSomething(),睡眠时间:1217线程执行LoggingWidget->doSomething(),睡眠时间:3958线程执行LoggingWidget->doSomething(),睡眠时间:4549线程执行LoggingWidget->doSomething(),睡眠时间:45710线程执行LoggingWidget->doSomething(),睡眠时间:18111线程执行LoggingWidget->doSomething(),睡眠时间:17012线程执行LoggingWidget->doSomething(),睡眠时间:47013线程执行LoggingWidget->doSomething(),睡眠时间:44414线程执行LoggingWidget->doSomething(),睡眠时间:11415线程执行LoggingWidget->doSomething(),睡眠时间:416线程执行LoggingWidget->doSomething(),睡眠时间:4017线程执行LoggingWidget->doSomething(),睡眠时间:32018线程执行LoggingWidget->doSomething(),睡眠时间:41619线程执行LoggingWidget->doSomething(),睡眠时间:148可见,不同线程调用同一个对象的synchronized方法,是不会重进入的,而是产生互斥锁.
转自:http://blog.csdn.net/haydenwang8287/article/details/5837734