多线程——synchronize的用法

synchronized介绍

因为在开发中会遇到“线程安全”与“非线程安全”相关的技术点,“非线程安全”其实会在对多个线程对同一个对象的实例变量进行并发访问时发生,产生的结果就是“脏读”,也就是取到的数据其实是被更改过的。而“线程安全”就是以获得的实例变量的值是经过同步处理的,不会出现“脏读”的现象。 因此为了解决“非线程安全”的问题就需要使用,也就是synchronized,synchronized可以有效地解决脏读问题。

synchronized的应用方式

一. 修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁。

Synchronized修饰一个方法很简单,就是在方法的前面加synchronized,synchronized修饰方法和修饰一个代码块类似,只是作用范围不一样,修饰代码块是大括号括起来的范围,而修饰方法范围是整个函数

需要注意的时,synchronized关键字不能被继承。在父类中的某个方法使用了synchronized关键字,而在子类中覆盖了这个方法,在子类中的这个方法默认情况下并不是同步的,需要在子类的方法再加上synchronized关键字才可以。不过,在子类中可以调用父类的同步方法,这样也可以去起到同步的作用

synchronized public void addI(){
      //TODO...
}

二. 修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象。

public void addI(){
    synchronized(this){
         //TODO...
    }
}

此时有一个线程访问一个对象中的同步代码块的时候,其他想要访问该对象的线程都会被阻塞。

其实java还支持对“任意对象”作为“对象监视器”来实现同步的功能。这个“任意对象”大多数是实例变量及方法的参数,使用格式为synchronized(非this对象)。

private String anyString = new String();
public void method3(SomeObject obj){
   //非this对象
   synchronized(anyString){
      //TODO...
   }
}

锁非this对象的优点是:如果当一个类中有很多个synchronized方法,这式虽然能实现同步,但会受到阻塞,所以影响运行效率。但是如果使用同步代码块锁非this对象,则synchronized(非this对象)代码块中的程序与同步方法是异步的,不与其他锁this同步方法争抢this锁,则可以提高运行效率。

三. 修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁。

public synchronized static void addI() {
    //TODO...
}

静态方法是属于类的而不属于对象的。同样的,synchronized修饰的静态方法锁定的是这个类的所有对象

四.修饰一个类,给class加锁和给静态方法加锁是一样的,所有对象公用一把锁。

class ClassName {
   public void addI() {
      synchronized(ClassName.class) {
        //TODO...
      }
   }
}

给class加锁和上例的给静态方法加锁是一样的,所有对象公用一把锁

死锁

Java多线程死锁是一个经典的问题,因为不同的线程都在等待根本不可能被释放的锁,从而导致所有的任务都无法继续完成。在多线程中死锁是必须避免的,因为这会造成线程的假死。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值