谈一下线程之间为什么是不可见的

前言:

因为最近刚学习线程相关的知识,所以想在此做一下笔记,顺带借此机会说一下自己对于相关知识的 理解以供参考;如在本文中发现有任何不妥的地方,请在评论区评论或与作者联系,以供修正;最后希望能在csdn这个平台与大家一起学习,共同进步。

 正文:

关于线程之间为什么是不可见的,谈到这个问题时我觉得有必要先了解一下线程执行时的一个内存空间;在Java中每一个的线程都有一块独立的内存空间,俗称线程工作区,当它们去执行临界区的资源(共享资源)时,都会先去主内存将共享资源复制一份到自己的工作内存中再进行操作,最后再把操作完的副本写入到主内存中;看似表面上是直接操作了共享资源,其实实际上是操作了共享资源的副本;

为了方便理解我画了流程图,如下:

线程内存之间的关系图:

 线程运行时的具体流程:

回到正题,相信看到这里不少的小伙伴对于线程不可见的问题在心里应该都有一个答案了;不过为了方便更多人的理解我还是阐述下致因吧;因为线程每次执行时都是要先拿取资源的副本,再在自己的工作内存里进行操作,最后再写入到主内存资源中;那这时容易出现一种情况,例如当多个线程要修改同一资源时,一个线程优先去复制了资源在自己内存进行操作时,突然某一线程趁机也偷偷的把资源复制到自己工作内存中操作,这时原先的那个先执行的线程执行完了操作把副本内容写入了主内存中时,偷偷摸摸的那个线程也跟着执行完了把结果写入到了主内存后,最后导致将原先执行的线程写入的结果给覆盖了,在这种情况下时我们就可以称之为线程之间的不可见。

同样为了方便大家理解也画了一个流程图(注意序号):

 为了方便大家更加深入的理解,以下文章还会通过a++这串代码来进行诠释:

总所周知a++是一个线程不安全的操作,那到底它不安全在哪里呢?为什么会出现这样的问题呢?让我们一起来解开这些疑问。

其实导致这个问题的原因正是我们之前说的线程之间的可见性问题,这时可能有的人就会问了,“诶,这不就只有一串代码吗?怎么会出现这样的问题呢(黑人问号脸)???”别急,接下来才是我们的重头戏,我们的java在执行这串代码的时候底层是通过多串指令来达成这个操作,拆解后分别是:先拿到变量a的值---再给a进行+1操作-----最后把得出的结果赋值给变量a;

这是a++操作通过字节码反编译出来的指令(有兴趣的可以去了解下javap)

通过上图就可以看到a++是由多段指令来完成的,再联系上文就清楚它为什么是线程不安全的操作了。

那么遇见这种问题时有没有什么解决办法?从我个人考虑的话解决的办法有两个,一个是锁机制,另一个是volatile关键字,如果各位有兴趣的话可以在下方评论,我会另外挑时间讲解下锁机制和volatile关键字,当然如果有其他的解决方法欢迎进行补充。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>