[Java] Synchronized关键字在使用时需要注意的情况

一、不要使用常量作为锁,比如String

以String为例,字符串是存在于常量池当中的,比如下面两个字符串a和b,这两个字符串的内容一样,他们的地址就会相同,

String a = "abc";
String b = "abc";

用下面的代码来说明,定义两个字符串a和b,在main方法中创建两个线程 ,分别取名为thread1和thread2;

首先,thread1线程会先执行,此时由于对象锁a是处于未被占有状态,因此thread1会直接拿到锁,并执行打印;

之后,thread2线程执行,因为对象锁b也是处于未被占有的状态,讲道理,会直接拿到锁并执行打印;

但是执行结果1却显示并没有打印thread2,这是因为a和b根本就是同一个对象,当thread1拿到锁a,并且在没有释放锁的情况下,锁"abc"(这里即:对象锁b)将是其他线程得不到的那个男人;

当我们将锁的类型换成Object时,就会得到另一番景象,执行结果2显示 thread1和thread1都各自拿到了锁,并执行打印;

public class ThreadConstant {
    // a和b对象地址相同
	String a = "abc"; 
	String b = "abc";

    // a和b对象地址不同
//	Object a = new Object();
//	Object b = new Object();

	private void getThread1(){
		synchronized (a){
			while (true) {
				System.out.println(Thread.currentThread());
			}
		}
	}

	private void getThread2(){
		synchronized (b){
			while (true) {
				System.out.println(Thread.currentThread());
			}
		}
	}

	public static void main(String[] args) {
		ThreadConstant tc = new ThreadConstant();
		new Thread(()->{
			tc.getThread1();
		}, "thread1").start();

		new Thread(()->{
			tc.getThread2();
		}, "thread2").start();
	}

}

执行结果1:thread1拿到锁,执行打印,,thread2未拿到锁,进入等待

在这里插入图片描述

执行结果2:thread1拿到锁,执行打印,,thread2拿到锁,执行打印。

在这里插入图片描述

二、不要在偏向锁的时候进行hashcode

在对象头里有块区域为markword
如果在无锁状态下,markword前25位一般是用来存放对象的hash值的
如果是偏向锁状态,那么markword前25位则是用来存储线程的id
因此,如果你进行了hashcode,那么该区域就只能用于存储hash值,就无法存放线程id了

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值