synchronized关键字修饰代码块

来源:互联网 发布:好帮手软件简介 编辑:程序博客网 时间:2024/06/04 01:21

转载请注明出处:http://blog.csdn.net/xingjiarong/article/details/47916703 
在上一篇博客中我们介绍了synchronized关键字修饰方法的用法,我们接着介绍synchronized关键字。除了修饰方法之外,还可以修饰代码块,一共有以下5种用法。

一、this

synchronizedthis){    //互斥代码}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

这里的this指的是执行这段代码的对象,synchronized得到的锁就是this这个对象的锁,这种写法等价于我们上一篇博客中讨论的:

public synchronized void func(){    //互斥代码}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

二、A.class

synchronized(A.class){    //互斥代码}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

这里A.class得到的是A这类,所以synchronized关键字得到的锁是类的锁,这种方法同下面的方法功能是相同的:

public static synchronized void fun(){    //互斥代码}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

所有需要类的锁的方法等不能同时执行,但是它和需要某个对象的锁的方法或者是不需要任何锁的方法可以同时执行。

三、object.getClass()

synchronized(object.getClass){    //互斥代码}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

这种方法一般情况下同第二种是相同,但是出现继承和多态时,得到的结果却是不相同的。所以一般情况下推荐使用A.class的方式。

四、object

synchronized(object){    //互斥代码}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

这里synchronized关键字拿到的锁是对象object的锁,所有需要这个对象的锁的方法都不能同时执行。

public class Trans {private Object lock = new Object();    public void printNum(int num){        synchronized (lock) {            System.out.print(Thread.currentThread());              for(int i=0;i<25;i++){                  System.out.print(i+" ");              }              System.out.println();        }              }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
class MyThread implements Runnable {      private Trans trans;      private int num;      public MyThread(Trans trans, int num) {          this.trans = trans;          this.num = num;      }      public void run() {          while (true)          {              trans.printNum(num);              try {                  Thread.sleep(500);              } catch (InterruptedException e) {                  e.printStackTrace();              }          }      }  }public class Test {      public static void main(String[] args) {          Trans t = new Trans();          Trans t1 = new Trans();          Thread a = new Thread(new MyThread(t, 1));          Thread b = new Thread(new MyThread(t1, 2));          a.start();          b.start();      }  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

在上边的例子中试图使用这种方法达到互斥方法打印方法,但是事实是这样做是没有效果的,因为每个Trans对象都有自己的Object对象,这两个对象都有自己的锁,所以两个线程需要的是不同锁,两个锁之间没有任何相互作用,所以不会起到互斥作用。

五、static object

上边的代码稍作修改就可以起到互斥作用,将Trans类中Object对象的声明改为下面这样:

private static Object lock = new Object();
  • 1
  • 1

这样不同的类使用的就是同一个object对象,需要的锁也是同一个锁,就可以达到互斥的效果了。

经过两篇博客的介绍,我们详细的讨论了synchronized关键字的用法,看似非常复杂,其实抓住要点之后还是很好区分的,只要看synchronized获得的是哪个对象或者类的锁就行啦,其他需要这个锁的方法都不能同时执行,不需要这个锁的方法都能同时执行。

最后还要告别一个误区,相信大家都不会再犯这种错误了,synchronized锁住的是一个对象或者类(其实也是对象),而不是方法或者代码段。

阅读全文
0 0