一、场景
程序里面使用了??synchronized???关键字,??IntelliJ IDEA??右边出现了黄色条,移动到上面,提示如下:
二、环境
软件
版本
JDK
1.8
IntelliJ IDEA
2019.1
三、原因
从提示来看,就是说,如果变量的引用发生了改变,就会导致??synchronized???失效,然后其他线程就会进入原本没有结束的??synchronized???代码块。所以要使用??final??来修饰变量,使引用不发生改变。
四、尝试
接下来让我们来验证一下,是否真的如提示所说。
错误范例
我写了以下代码,请各位读者看:
public class Test1 implements Runnable{ private Byte[] flag = new Byte[1]; @Override public void run() { synchronized (flag){ System.out.println(new Date()+” 开始休眠”+Thread.currentThread().getName()); flag = new Byte[11]; try { Thread.sleep(10000); System.out.println(new Date()+” 结束休眠”+Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) throws InterruptedException { Test1 test = new Test1(); new Thread(test).start(); Thread.sleep(100); new Thread(test).start(); }}
如果??synchronized ??关键字有生效的话,就会导致前后两个线程会间隔10秒打印日志。结果如下:
Fri Apr 10 22:03:43 CST 2020 开始休眠Thread-0Fri Apr 10 22:03:43 CST 2020 开始休眠Thread-1Fri Apr 10 22:03:53 CST 2020 结束休眠Thread-0Fri Apr 10 22:03:53 CST 2020 结束休眠Thread-1
从结果可以看到,中间两个线程基本没有间隔就开始了。和我们的预期是存在差异的。那是什么原因导致了变量的引用发生了改变吗?就是代码里面的那行重新赋值的语句:
flag = new byte[11];
所以,也正如提示所说的,就是因为变量的引用发生了改变,所以导致了??synchronized ??关键字没有生效。接下来就让我们开始正确的尝试阶段。
正确范例
我对??错误范例???里面的代码进行优化,在这里主要按照提示所说,加上??final??来使得对象不必改变,各位读者跟随我的思路来。
public class Test1 implements Runnable{ private final Byte[] flag = new Byte[1]; @Override public void run() { synchronized (flag){ System.out.println(new Date()+” 开始休眠”+Thread.currentThread().getName()); flag[0] = 11; // 因为变量设置为了final,没有办法进行修改。故注释掉。 //flag = new Byte[11]; try { Thread.sleep(10000); System.out.println(new Date()+” 结束休眠”+Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) throws InterruptedException { Test1 test = new Test1(); new Thread(test).start(); Thread.sleep(100); new Thread(test).start(); }}
结果如下:
Sun Apr 12 00:25:33 CST 2020 开始休眠Thread-0Sun Apr 12 00:25:43 CST 2020 结束休眠Thread-0Sun Apr 12 00:25:43 CST 2020 开始休眠Thread-1Sun Apr 12 00:25:53 CST 2020 结束休眠Thread-1
从结果来看,这个时候的??synchronized ???是已经生效了。因为加了??final??,导致变量无法被改变引用。
五、总结
并发情况下面,一个变量如果是打算作为锁,就得考虑是否会被更新引用的情况。所以,并发情况下,还是要多思考,才能写出质量上乘的代码。
随缘求赞
如果我的文章对大家产生了帮忙,可以在文章底部点个赞或者收藏;如果有好的讨论,可以留言;
如果想继续查看我以后的文章,可以点击关注可以扫描以下二维码,关注我的公众号:枫夜之求索阁,查看我最新的分享!
【转自:阜宁网站设计 funing.html 欢迎留下您的宝贵建议】天下没有不散的宴席,也许这人间真的只有朦朦胧胧才是真。