java并发编程实践第二遍笔记(二)20171017

来源:互联网 发布:c语言笔试题大一带答案 编辑:程序博客网 时间:2024/06/06 09:04

对象的共享

如何共享和发布对象,使他们能够安全地由多个线程同时访问。
synchronized 可以保证可见性和原子性。
内存的重排序只能保证在单线程中不出问题,在多线程中不能保证。
重排序:在没有同步的情况下,编译器、处理器以及运行时等都可能对操作的执行顺序进行一些调整。
最低安全性在大多数情况下能得到保证,但是存在一个例外:非valatile类型的64位数值变量(double,long)。因为jvm允许读写操作分解为两个32位的操作。当被多个线程操作时就会读到某个值的高32位,另一个值的低32位。(大部分虚拟机做了优化不会出现这种问题,不过为了写出更健壮的程序还是用volatile或synchronized来保证原子性比较好)。
volatile修饰的变量不会被重排序。
一般满足下列情况时才建议用volatile否则建议用synchronized这样写出的程序更容易理解更健壮。volatile的具体实现原理先不了解不是目前的重点,用的时候就当是加了锁的get,set方法虽然不完全正确。
仅当volatile变量能简化代码的实现时才应该使用它。例如:
volatile通常用做某个操作完成、发生中断或者状态的标志。

对象的发布即:是对象能够在自己的作用域范围外被引用。
对象在没有构造完成之前不应该发布。

线程封闭:
例如JDBC隐式的将connection封闭在线程中。
ad-hoc线程封闭是指维护线程封闭性的指针完全有程序实现来承担。
栈封闭:在栈中封闭即局部变量
ThreadLocal类

不变性
如果某个对象在被创建后其状态就不能被修改,那么这个对象就称为不可变对象。线程安全是不可变对象的固有属性之一,也就是说不可变对象一定是线程安全的。
不可变对象很简单。他们只有一种状态,并且该状态由构造函数来控制。
java的不可变对象并不是等于将对象中所有的域都声明为final类型,即使对象中所有的域都是final类型的,这个对象也仍然是可变的,因为在final类型的域中可以保存对可变对象的引用。
当满足以下条件时,对象才是不可变的:
对象创建以后其状态就不能修改。
对象是正确创建的。

正如”除非需要更高的可见性,否则应将所有的域都声明为私有域”是一个良好的编程习惯,“除非需要某个域是可变的,否则应将其声明为final域”也是一个良好的编程习惯。

每当需要对一组相关数据以原子性方式执行某个操作时,就可以考虑创建一个不可变的类来包含这些数据。

即使某个对象的引用对其他线程是可见的,也并不意味着对象状态对其他线程是可见的。

todo

安全的发布对象方面的知识看起来还有些吃力知识储备不够,到时要重点看。
原创粉丝点击