多线程笔记(一)

Q1.一个类中同时有synchronized和非synchronized方法,一个线程调用synchronized方法时,另一个线程能不能调用非synchronized方法?

A1.能。因为第二个线程调用非synchronized方法时,不需要申请堆内存里的锁。就像第一个线程去上厕所把门锁住了,第二个线程去厨房,不需要进厕所,所以可以调用。注意synchronized方法锁定的是调用该方法的对象。

 

Q2.synchronized获取的锁可重入吗?

A2.可重入。在一个线程中,调用一个synchronized方法,该方法中又调用另一个synchronized方法,再次申请锁的时候仍然可以得到锁,锁的次数从1变成2。同样的,子类synchronized方法可以调用父类synchronized方法获取锁。两次锁定的是同一个对象,都是this。

 

Q3.发生异常时会释放锁吗?

A3.发生异常时,默认会释放锁,必须小心处理异常。以银行转账为例,调用synchronized转账方法时,先从A的账户上扣去100元,再在B的账户上加上100元。如果多个线程对A账户调用转账方法,而第一个线程扣完100元后抛出了异常,如果不处理,锁会被释放,第二个线程获取到锁,再从A账户上扣去100元,C账户上加上100元,这样就会出现问题。

 

Q4.volatile关键字

A4.一个线程中的volatile变量发生改变时,会通知其它线程他们缓存中的这个变量值过期了,应当从主内存中再读一次。volatile关键字能保证线程之间变量的可见性,但不能保证操作的原子性,是一种无锁同步,效率比synchronized高得多,但不能替代synchronized。例如,定义全局的volatile int count,再定义add方法循环10000次,每次count++,起10个线程一起调用add方法,按照道理count最后会加到100000.但由于count++不是原子操作,虽然每个线程读count的时候都是正确的count,但多个线程都读到一个count值,count+1,再给count赋值,就发生了重复的情况。

 

Q5.String s1 = "hello"; String s2 = "hello"; synchronized(s1),synchronized(s2)为什么会死锁?

A5.因为锁是锁在堆内存上的,锁的是"hello"这个字符串对象,而不是s1,s2的引用。开发中不要锁定字符串常量,因为如果引用的jar包里也锁定了这个字符串常量,将产生死锁。并且这种死锁非常隐蔽,不容易debug出来。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值