Java 中的 Synchronized 关键字


synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:

  1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
  2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
  3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
  4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

修饰一个代码块

一个线程访问一个对象中的synchronized(this)同步代码块时,其他试图访问该对象的线程将被阻塞。

多个线程访问不同对象的时候,执行到这个代码块的时候,均会执行该方法,不会发生方法上锁的情况。

多个线程访问同个对象的一个方法

结果:谁拿到锁谁执行,没拿到的等待

多个线程访问多个对象的一个方法

结果:多个线程各自访问各自拥有对象的方法:

Synchronized 锁一个明确的对象

新建卖票类,sell 方法卖出一张票减一,addTicket 方法补一张票的库存。

新建卖票线程,在 run 方法里面每卖一张票就补一张票的库存。

最后开启五个卖票线程去卖票:

结果:

可以看到这里的并不是 从 A B C D E 依次执行的,因为谁拿到执行权就谁去执行。

没有明确的锁,只是为了给一块代码加上同步

说明:零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码

修饰一个方法

Synchronized 修饰一个方法的格式是

public Synchronized void run(){
    // code
}

Synchronized 关键字修饰的是整个函数里面的内容,当相同对象在多线程访问的 run 方法的时候,由于被 Synchronized 关键字修饰,不能同时访问。

这种写法等价于修饰代码块的这种写法:

public void run(){
    Synchronized(this){
        // code
    }
}

两种写法的 code 都是可以互斥访问的。

Synchronized 修饰方法的注意事项:

  1. Synchronized 修饰方法不能被子类继承
  2. 接口中不能写 Synchronized
  3. 构造方法不能使用synchronized关键字,但可以使用synchronized代码块来进行同步。

修饰一个静态的方法

这种情况也是针对于所有对象的这个方法,当多个线程访问这个代码块的时候,均会进行资源竞争的情况,谁拿到锁谁执行,没拿到的等待。

使用方法:

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

Synchronized 作用在静态方法中,相当于给整个类加了锁,不管是类的哪个对象访问这个方法的时候,都会竞争锁的资源.

需要注意的是:对其他没加 Synchronized 的方法没有影响。

加上 Synchronized 关键字

结果:

不加 Synchronized

结果:

修饰一个类

这种情况也是针对于所有对象的这个方法,当多个线程访问这个代码块的时候,均会进行资源竞争的情况,谁拿到锁谁执行,没拿到的等待。

使用方法:

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

结果:顺序执行,A 获得锁以后,B 只能等待 A 释放

不使用 synchronized(ClassName.class)

结果:谁竞争到执行权,执行谁

总结:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值