使用synchronized的几种场景

2017-04-17  本文已影响656人  金馆长说

同步关键字用于在多个线程中需要对同一段数据进行访问时候,出现的不安全情况。因为多个线程执行同一段代码会造成数据不安全,所以需要用synchronized来同步代码。

修饰一个类
其作用的范围是synchronized后面括号括起来的部分,作用的对象是这个类的所有对象,只要是这个类型的class不管有几个对象都会起作用。如下代码

class ClassName {
    public void method() {
       synchronized(ClassName.class) {
          // todo
       }
    }
 }

修饰一个方法
synchronized 修饰一个方法很简单,就是在方法的前面加synchronized,例如:

public synchronized void method()
{
   // todo
}

在定义接口方法时不能使用synchronized关键字。
构造方法不能使用synchronized关键字,但可以使用synchronized代码块来进行同步。
synchronized 关键字不能被继承 ,如果要同步需要显式的加上关键字。
synchronized 关键字修饰的方法如果被重写默认不同步,如果要同步需要显式的加上关键字,或者super父类的方法也就相当于同步了。

修饰代码块

public  void method()
{
   synchronized(this)
   synchronized(XX.class)
}

synchronized(this)锁的是当前对象,当前有几个对象那么这个this就是有多份,这里的this只能锁同一个对象。
synchronized(XX.class)只要是这个类型的class这把锁就都有用

当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
以上规则对其它对象锁同样适用.

修饰静态方法
我们知道 静态方法是属于类的而不属于对象的 。同样的, synchronized修饰的静态方法锁定的是这个类的所有对象,所有类用它都会有锁的效果。

public synchronized static void method() {
   // todo
}

总结:

A. 无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;如果synchronized作用的对象是一个静态方法或一个类,则它取得的锁是对类,该类所有的对象同一把锁。
B. 每个对象只有一个锁(lock)与之相关联,谁拿到这个锁谁就可以运行它所控制的那段代码。
C. 实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。
D.同步关键字锁的是对象

参考

上一篇下一篇

猜你喜欢

热点阅读