【面试题】sychronized


synchronized 翻译成中文是同步的的意思,主要解决的是多个线程之间访问资源的同步性,可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。

1. 如何使用 synchronized 关键字?

Synchronized是一个同步关键字,在某些多线程场景下,如果不进行同步会导致数据不安全,而Synchronized关键字就是用于代码同步。什么情况下会数据不安全呢,要满足两个条件:一是数据共享(临界资源),二是多线程同时访问并改变该数据。

1.1 修饰静态方法

修饰静态方法,对当前类的Class对象加锁,也就是SyncDemo.class对象

public class SynDemo {
    static int value = 0;
    public synchronized static void testStaticSync() {
        value++;
    }
}

1.2 修饰实例方法

修饰实例方法,对当前实例对象this加锁

public class SynDemo {
    int i = 0;
    int x = 0;
    public synchronized void  testSync() {
        i++;
        x++;
    }
}

1.3 在方法内部的同步代码快

修饰代码块(锁指定对象/类)
synchronized(object) 表示进入同步代码库前要获得 给定对象的锁。
synchronized(类.class) 表示进入同步代码前要获得 给定 Class 的锁

synchronized注意事项

(1)定义一个TestThread类,继承自Thread
(2)TestThread的内部持有一个SycDemo对象
(3)TestThread的run方法内部调用SyncDemo对象的testSync方法执行synchronized修饰的同步方法。

public class SynDemo {
    int i = 0;
    int x = 0;
    // 争抢对象SyncDemo的锁
    public synchronized void  testSync() {
        i++;
        x++;
    }
 
    static class TestThread extends Thread {
        SynDemo lock;
        TestThread(SynDemo lock) {
            this.lock = lock;
        }
        @Override
        public void run() {
            lock.testSync();
        }
    }
 
    public static void main(String[] args) {
        // 锁对象lock1
        SynDemo lock1 = new SynDemo();
        // 锁对象lock2
        SynDemo lock2 = new SynDemo();
        
        TestThread threadA = new TestThread(lock1);
        TestThread threadB = new TestThread(lock2);
        
        threadA.start();
        threadB.start();
    }
}

像这种方式,threadA和threadB是达不到互斥的目的的,因为threadA锁住的是lock1对象;然而thread锁住的是lock2对象。完全争抢的不是同一个锁。
在这里插入图片描述
那如果要使得threadA和threadB达到同步的目的,应该怎么做?

需要threadA和threadB争抢同一把锁,争抢同一个同一个对象的锁才可以,也就是像下面那样,也就是threadA和threadB都使用同一对象锁ock1,这样才是正确的:

public static void main(String[] args) {
    // 只有一个锁对象lock1
    SynDemo lock1 = new SynDemo();
    // 两个线程对同一个对象锁进行争抢
    TestThread threadA = new TestThread(lock1);
    TestThread threadB = new TestThread(lock1);
 
    threadA.start();
    threadB.start();
}

在这里插入图片描述
对于synchronized修饰static的方法,synchronized锁的是这个类对象,由于类对象只有一个,所以不同线程同时通过类调用这个方法的时候就能互斥的效果。

2. synchronized 关键字的底层原理

2.1 同步代码块

synchronized 同步语句块的实现使用的是 monitorenter 和 monitorexit 指令,其中 monitorenter 指令指向同步代码块的开始位置,monitorexit 指令则指明同步代码块的结束位置。

2.2 同步方法

JVM 通过该 ACC_SYNCHRONIZED 访问标志来辨别一个方法是否声明为同步方法,从而执行相应的同步调用。

3. 特性

如何保证三大特性

3.2 可重入特性

3.2.1 可重入原理

synchronized是可重入锁,内部锁对象中会有一个计数器记录线程获取几次锁,在执行完同步代码块时,计数器的数量会-1,知道计数器的数量为0,就释放这个锁。

3.2.2 可重入的好处

  1. 可以避免死锁
  2. 可以让我们更好的来封装代码

3.3 不可中断特性

一个线程获得锁后,另一个线程想要获得锁,必须处于阻塞或等待状态,如果第一个线程不释放锁,第二个线程会一直阻塞或等待,不可被中断。

4. synchronized底层到底是怎么加锁的

5. synchronized的锁重入、锁消除、锁升级原理

无锁-》偏向锁-》轻量级锁-》重量级锁
锁可以升级不可以降级,但是偏向锁状态可以被重置为无锁状态。
在这里插入图片描述

6. 为什么说synchronized是重量级锁

7. 平时写代码如何对sychronized优化

1.减少sychronized的范围,同步代码块尽量短,减少同步代码块的执行时间,减少锁竞争。
2.降低sychronized锁的颗粒度(HashTable锁定方法 和 ConcurrentHashMap局部锁定,锁定桶)
在这里插入图片描述
3.读写分离(读取不加锁,增加删除的时候加锁)
ConcurrentHashMap,CopyOnWriteArrayList,CopyOnWriteSet

8. synchronized(string)使用

文章出处:https://www.bilibili.com/video/BV1aJ411V763?p=29&vd_source=b901ef0e9ed712b24882863596eab0ca
参考链接:https://blog.csdn.net/tongdanping/article/details/79647337
如何使用:https://blog.csdn.net/chenzengnian123/article/details/122683126

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值