Posted on 2012-05-07 14:14
luofeng 阅读(200)
评论(0) 编辑 收藏 引用 所属分类:
Java
《并发编程实践》
-----------------------
并发基础
编写线程安全的代码, 本质上就是管理对状态的访问,而且通常都是共享的, 可变的状态.
竞争条件
最常见的一种竞争条件是"检查再运行(check-then-act)", 使用一个潜在的过期值作为下一步操作的依据.
检查再运行: 你观察到一些事情为真, 然后基于你的观察去执行一些动作, 但事实上, 从观察到执行操作的这段时间内, 观察结果可能已经无效了, 从而引发错误.
原子操作
假设有操作a和b, 如果从执行a的线程的角度看, 当其他线程执行b时, 要么b全部执行完成, 要么一点也没有执行, 那么a和b就互为原子操作.
为了保证线程安全, "检查再运行"操作和"读-改-写"操作必须是原子操作.
锁的可重入特点
线程在试图获得它自己占有的锁时, 请求线程将会成功, 重进入意味着所有的请求都是基于"每线程", 而不是基于"每调用".
共享对象
同步同样还有一个重要而微妙的方面: 内存可见性. 我们不仅希望能够避免一个线程修改其他线程正在使用的对象的状态, 而且希望确保当一个线程修改了对象的状态之后, 他线程能够真正看到改变.
锁不仅是关于同步与互斥的, 也是关于内存可见的, 为了保证所有线程都能看到共享的, 可变变量的最新值, 读取和写入线程必须使用公共的锁进行同步.
逸出
如果一个对象还没有完成构造就发布了, 这种情况就是逸出.
死锁
当每个人都拥有他人需要的资源, 并且等待其他人正在占有的资源, 如果大家一直占有资源, 直到获得自己需要却没被占用的资源, 那么就会产生死锁.
当一个线程永远占有一个锁, 而其他线程尝试去获得这个锁, 那么它们将永远被阻塞. 当线程占有锁L时, 想要获得锁M, 但是同时, 线程B持有M, 并尝试获得L, 两个线程将永远等待下去, 这种情况是死锁的最简单的形式.