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

一、简介

  1. java多线程的问题:线程安全问题,活跃性问题(多线程死锁,单线程无限循环),性能问题(主要是频繁的切换上线文的开销)
  2. 多线程无处不在,servlet RMI。

二、线程安全性

修复线程安全问题的方式:
不在线程之间共享该状态变量。
将状态变量修改为不可变的变量。
在访问状态变量时使用同步。

尽量编写可维护性高的类。

为了保证类的线程安全最好要把同步机制封装在类内部。

无状态的类:既不包含任何域,
无状态的类一定是线程安全的。
静态条件的类型:先检查后执行
静态的synchronized为类的锁,非静态的锁为对象的锁。
synchronized是可重入的。即在同一个线程中可以调用同一个锁的不同synchronized代码块。
一种常见的错误是认为只有在写入共享变量时才需要使用同步,然而事实并非如此,原因并非如此因为即使写的时候同步了写完把最新的数据刷到共享内存中了但是如果不加同步代码块读的时候一定会从共享内存中去读而是在自己的内存栈中读,这时候读到的就不是最新的。

一种常见加锁约定是:将所有的可变状态都封装在对象内部,并通过对象的内置锁对对所有访问可变状态的代码路径进行同步,使得该对象不会发生并发问题。但是并不能保证一定是线程安全的因为不光要加锁还需要正确的加锁比如保证足够的原子性,比如UnsafeCachingFactorizer类就是没有保证足够的原子性。

锁的颗粒度越小效率越高?不一定例如在CachedFactorizer中将++hits分解到自己的代码块中,并不一定能能提高性能因为在获取锁与释放锁等操作上需要一定的开销。所以说加锁的时候应该在简单些(对整个方法加锁)和并发现(尽可能西的颗粒度)之间的平衡。

要判断同步代码块的合理大小,需要在各种设计需求之间进行权衡,包括安全性(必须满足)、简单性和性能。通常,再简单性与性能之间存在着相互制约的因素。当实习某个同步策略时,一定不要盲目地为了性能而牺牲简单性。
当使用锁时,你应该清楚代码块中实现的功能,以及在执行代码块时是否需要很长的时间。无论是执行计算密集的操作还是某个可能阻塞的操作,如果持有锁的时间过长,那么都会带来活跃性或性能问题。
当执行时间长的计算或者可能无法快速完成的操作(例如,网络I/O或控制台I/O),一定不要持有锁。

对于单个变量上实现原子操作来说,原子变量很有用,但是对于多个变量的原子操作来说就没有用了。

实现runable为什么比继承Thread接口类更容易共享变量,想想他们的使用场景就明白了。由于使用实现runable比继承Thread简单明了所以除非打算需改或增强类的基本行为,否则尽量用runable。
避免了java单继承的局限性。
http://mars914.iteye.com/blog/1508429

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值