JAVA多线程中的面试知识点(一)

359 阅读2分钟

这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

1. synchronized

同步方法与同步块的区别:

1.同步方法
同步方法锁定的是this对象,不是方法。 即有synchronized关键字修饰的方法。由于java的每个对象都有一个内置锁,当用此关键字修饰方法时,内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。代码如:

public synchronized void save(){}

2.同步代码块
即有synchronized关键字修饰的语句块。 被该关键字修饰的语句块会自动被加上内置锁,从而实现同步。代码如:

synchronized(object){ 
}

注:同步是一种高开销的操作,因此应该尽量减少同步的内容。通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。

在选择加锁对象的时候,加锁的时候应该加在大对象上,防止调用对象不是同一个。

2.volatile

只保证数据同步,当数据修改时立即通知其他持有者更新数据。比synchronized开销小,但不保证操作的原子性。已经很少使用了。

3.使用double-checking和volatile进行单例设计

单例模式:套路,在多线程环境下,对外存在一个对象。 在懒汉式基础上修改。

  1. 构造器私有化,防止外部创建
  2. 提供私有的静态属性
  3. 提供公共的静态方法 静态方法示例:
public static DoubleCheckedLocking getInstance(){
    //再次检测,减少不必要的同步。
    if(null !== instance){return instance}
    
    synchronized(DoubleCheckedLocking.class){
        if(null == instance){
            instance = new DoubleCheckedLocking();
        }
    }
    return instance;

}instance

4.可重入锁

原理:锁添加计数器,当加锁对象被访问时,判断是否锁定且为当前持有锁对象,否则wait();,是则计数器加1,当计数器为0时说明对象释放锁。

例子:ReentrantLock。

5.乐观锁和悲观锁

悲观锁

独占锁,会导致其他线程挂起。

乐观锁

没有锁,在提交的时候比较值,如果失败重试,直到成功。
乐观锁实现方式:CAS(Compare and Swap ),中文翻译成比较并交换。 具体实现为需要读写的内存位置(V)、进行比较的预期原值(A)和拟写入的新值(B)。如果内存位置V的值与预期原值A相匹配,那么处理器会自动将该位置值更新为新值B。否则处理器不做任何操作。CAS有效地说明了“我认为位置V应该包含值A;如果包含该值,则将B放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。