1. 字符串加锁
不建议对字符串加锁,字符串比较特殊,一般情况下在内存中只有一份儿,两个线程分别对同一个字符串加锁,非常容易产生阻塞,甚至是死锁。而且如果用法不对,加锁毫无效果。
/**
* 字符串加锁
* 不建议对字符串加锁,字符串比较特殊,一般情况下在内存中只有一份儿,两个线程分别对同一个字符串加锁,非常容易产生阻塞,甚至是死锁。而且如果用法不对,加锁毫无效果。
*/
public class T04_Synchronized {
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
show("feng");
}).start();
new Thread(() -> {
show(new String("feng"));
}).start();
}
public static void show(String str){
synchronized (str){
// synchronized (str.intern()){ // 如果字符串池中存在当前字符串, 就会直接返回当前字符串. 如果没有, 会将字符串放入池中后, 再返回
System.out.println(str);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2. 锁升级过程
简单过程
- 第一次加锁,偏向锁,记录Thread Id
- 另一个线程来,发现Thread Id 不同,锁升级:轻量级锁,又称 自旋锁
- 自旋一定次数后仍然抢不到锁,升级为重量级锁,线程挂起,等待
轻量级和重量级锁的使用,轻量级自旋时很消耗cpu
如果线程数少,而且运行速度较快,适合轻量级锁,反之使用重量级锁