Java多线程学习零散笔记

来源:互联网 发布:windows安装redis步骤 编辑:程序博客网 时间:2024/06/07 07:43
笔记笔记比较零散,后期整理成篇幅




多线程中的同步其实是有两成含义的:
1:互斥访问(原子性)
2:变量的修改对其他线程可见(可见性)
synchronized同步关键字就保证了上述两层含义,而volatile只保证了第二条:变量的修改对其他线程可见




可见性:可见性是一种复杂的属性。在单个线程的程序中,如果想某个变量写入数值之后,在没有其他写操作的之前一直都可以读取到之前写入的数值,这很符合我们
日常看法的直觉,但是读写操作分别在不同的线程之后,我们无法保证读操作能够实时看到写操作之后的数值(除非使用同步机制)。为了确保多线程之间对内存的写
入操作的可见性,必须使用同步机制。




非原子的64位操作:当没有线程同步读取一个变量时候可能读取一个失效的数值,然后这个失效的数值可能使我们之前设置过的,而不是一个
随机数值。这种安全性保证我们称之为最低安全性保证。最低安全性保证适用于大多数变量,但是存在一个特例:
非volatile类型的64位数值变量(double和long)。Java内存模型要求变量的读操作和写操作都是原子操作,但是对于非volatile的long和double变量,JVM允许将64位操作划分为
两个32位操作。当读取一个非volatile的long(或double)变量时候,当读和写操作在多个线程时候可能会读取一个到某一个值高于32位另一个值低于32位。因此不考虑读取失效数据的情况下,
在多线程中使用共享可变的long或者double变量时候是线程不安全的,除非使用关键字volatile关键字或者使用锁保护起来



Java提供了一种稍弱的同步机制,即volatile变量,用来确保将变量的更新操作通知到其他线程中。当把变量声明为volatile类型后,编译器和与运行时会注意到这个变量是
共享的,因此不会将该变量的操作和其他内存操作进行重排序。volatile变量也不会缓存在寄存器或者对其他处理器不可见的地方,因此读取volatile变量时候总是能获取到最新写入的数值。



当且仅当满足一下条件时候才可以使用volatile关键字:
1:对变量的写入操作不依赖变量的当前值或者你能确保只有单个线程更新变量的值(不需要原子性的保证只需要可见性保证)
2:访问该变量时候不需要加锁(还是不需要原子性保证,只需要可见性保证)


总结:只要不需要原子性保证(互斥访问),只需要可见性保证时候使用volatile关键字















































































0 0
原创粉丝点击