线程安全与线程同步的学习发布时间:2020/8/19 17:03:27 阅读次数:

  

线程安全

JVM内存中的堆区,是一个共享的区域,是所有线程都可以访问的内存空间。
JVM内存中的栈去,是线程的私有空间,每个线程都有自己的栈区,别的先无法访问到自己栈区
的数据。
如果代码只有一个main线程,只有它自己去访问堆区中的对象数据,自然没有什么问题,但是在多线程的环境中,如果有两个线程并发访问堆区中一个对象中的数据,那么这个数据可能就会出现和预期结果不符的情况。
举例来说

image.png

运行结果为下图

2020081719284337.png

可以看出预期与结果不符
此时内存图为:

20200817193147736.png

t1线程操作一下变量num,然后时间片用完退出去,t2先过来又操作了变量num, 等t1线程再过来的时候,这值已经被t2线程给“偷偷”修改了,那么就出现了和预期不符的情况

总结

出现数据结果和预期不符的情况,这种情况就是线程安全问题。
一般线程安全问题都会包含以下三个条件

1.   多个线程并发运行

2.   访问同一个共享变量

3.   具有写操作

线程同步

Java中提供了线程同步的机制,来解决上述的线程安全问题。
Java中实现线程同步的方式,是给需要同步的代码进行 synchronized 关键字加锁

例如,将上面的有安全问题的代码进行改造,给需要同步的代码使用synchronized加锁

image.png

image.png


运行结果如下图

2.png

线程同步的效果,就是一段加锁的代码,每次只能有一个拿到锁的线程,才有资格去执行,没有拿到的锁的线程,只能等拿到锁的线程把代码执行完,再把锁给释放了,它才能去拿这个锁然后再运行代码。

这样以来,本来这段代码是俩线程并发访问,“争先恐后”的去执行的,现在线程同步之后,这段代码就变成了先又一个拿到的锁的先去执行,执行完了,再由另一个线程拿到锁去执行。

相当于是大家每个线程不要抢,排好队一个一个去执行,那么这时候共享的变量的值,肯定不会出现线程安全问题