Java 阻塞队列
ArrayBlockingQueue
LinkedBlockingQueue
SynchronousQueue
用put() 和 take() 是阻塞
不要用poll()和offer() ,要用也要用带时间参数的
锁是控制多个线程对共享资源进行访问的工具。通常,锁提供了对共享资源的独占访问。一次只能有一个线程获得锁,对共享资源的所有访问都需要首先获得锁。不过,某些锁可能允许对共享资源并发访问,如
ReadWriteLock
的读取锁。
synchronized 每个对象相关的隐式监视器锁的访问,强制所有锁获取和释放均要出现在一个块结构中:当获取了多个锁时,它们必须以相反的顺序释放,且必须在与所有锁被获取时相同的词法范围内释放所有锁。
Lock
Lock
实现提供了使用 synchronized
方法和语句所没有的其他功能,包括提供了一个非块结构的获取锁尝试 (tryLock()
)、一个获取可中断锁的尝试 (lockInterruptibly()
) 和一个获取超时失效锁的尝试 (tryLock(long, TimeUnit)
)。
Lock
类还可以提供与隐式监视器锁完全不同的行为和语义,如保证排序、非重入用法或死锁检测。如果某个实现提供了这样特殊的语义,则该实现必须对这些语义加以记录。
ReentrantLock
一个可重入的互斥锁
Lock
,它具有与使用
synchronized
方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。
Condition
Condition
将
Object
监视器方法(
wait
、
notify
和
notifyAll
)分解成截然不同的对象,以便通过将这些对象与任意
Lock
实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,
Lock
替代了
synchronized
方法和语句的使用,
Condition
替代了 Object 监视器方法的使用。
使用Atomic 包
使用阻塞队列
lock-free 算法
1 循环 ( for (;;))
2 CAS compareandset
Compareand-Swap
原子操作指一个cpu时钟周期内就可以完成的操作,不会被其他线程干扰。
{if( *pVal == oldVal ) { *pVal = newVal; return true;} return false;}
3 回退
锁
1 使用CAS结构的数据结构,避免使用锁,如AtomicXXX、ConcurrentMap、CopyOnWriteList、ConcurrentLinkedQueue
2 注意锁的顺序
3, 通过dump kill -3 等查看死锁信息
4 注意外部锁,比如数据库的锁 文件的锁
Map 用ConcurentHashMap 取代
避免直接使用锁,锁由数据结构管理
ScheduledExecutorService,不建议你再使用java.util.Timer
Amdahl 定律
– Gene Amdahl 发现在计算机体系架构设计过程中,即使你有10个老婆,也不能
某个部件的优化对整个架构的优化和改善是有 一个月把孩子生下来。
上限的。这个发现后来成为知名的Amdahl 定律。
•Gustafson 定律
– Gustafson假设随着处理器个数的增加,并行与 当你有10个老婆,就会要生
串行的计算总量也是可以增加的。Gustafson定
律认为加速系数几乎跟处理器个数成正比,如 更多的孩子。
果现实情况符合Gustafson定律的假设前提的话,
那么软件的性能将可以随着处理个数的增加而
增加。
•Sun-Ni 定律
– 充分利用存储空间等计算资源,尽量增大问题 你要设法让每个老婆都在干
规模以产生更好/更精确的解。 活,别让她们闲着。
CountDownLatch
当你启动很多线程,你需要这些线程等到通知后真正开始,用countdownlatch
当你启动了一个线程,你需要等它执行结束, 此时,CountDownLatch也许是一个很好的选择。
CAS注
CAS在我的理解就是下面这段代码
{if( *pVal == oldVal ) { *pVal = newVal; return true;} return false;}
当然,CAS把这段代码做成了一个原子操作。
很多人看到这里,并不是十分理解,这个原子操作怎么去实现LOCK FREE。
一般CAS会封装成下面的形式
bool cas32( int * pVal, int oldVal, int newVal );
pVal 表示要比较和替换数值的地址,oldVal表示期望的值,newVal表示希望替换成的值。在多线程中使用时,一般是下面这样。
volitale int myValue;
......
while( !cas32( &myValue, myValue, myValue+1 ) ) {
....
}
这是什么意思呢?
我们知道,在多线程里面,如果多个线程同时在写一个变量,并且不进行同步的时候,这个变量的值就会不准确。比如两个线程同时在对一个变量进行+1操作的时候,他们分别需要进行三个操作,读入变量值(到寄存器),值+1,写入变量值(到变量内存地址)。这三个操作是无法保证原子性的,也就无法保证变量在读入,+1后,原变量没有被别的线程修改。
cas在这里做的实际上就是在变量没有被其他线程修改,或者被修改但是又恢复到我们期望读入的值的时候,修改变量的值。这句话很拗口,其实看CAS的参数就很容易理解,pVal传递进去的是变量的地址,cas通过这个来读取变量真实的值,oldVal传递的是变量在函数调用时的值,用来跟真实值进行比较,而newVal传递进去的是期望变量赋予的新的值。根据上面的cas的代码含义我们知道,当变量真实值不等于调用时的值的时候,是不会赋予变量新的值的。所以我们使用了一个WHILE来等待这个赋值成立。同时我们给与myValue一个volitale修饰,用意是让while中调用cas函数时,读取myValue的当前值,而不是寄存器中保存的值,以免变量值的“过期”,从而让这个cas可以在没有其他线程来修改myValue的时候执行成功,从而实现lock free的修改myValu
{if( *pVal == oldVal ) { *pVal = newVal; return true;} return false;}
当然,CAS把这段代码做成了一个原子操作。
很多人看到这里,并不是十分理解,这个原子操作怎么去实现LOCK FREE。
一般CAS会封装成下面的形式
bool cas32( int * pVal, int oldVal, int newVal );
pVal 表示要比较和替换数值的地址,oldVal表示期望的值,newVal表示希望替换成的值。在多线程中使用时,一般是下面这样。
volitale int myValue;
......
while( !cas32( &myValue, myValue, myValue+1 ) ) {
....
}
这是什么意思呢?
我们知道,在多线程里面,如果多个线程同时在写一个变量,并且不进行同步的时候,这个变量的值就会不准确。比如两个线程同时在对一个变量进行+1操作的时候,他们分别需要进行三个操作,读入变量值(到寄存器),值+1,写入变量值(到变量内存地址)。这三个操作是无法保证原子性的,也就无法保证变量在读入,+1后,原变量没有被别的线程修改。
cas在这里做的实际上就是在变量没有被其他线程修改,或者被修改但是又恢复到我们期望读入的值的时候,修改变量的值。这句话很拗口,其实看CAS的参数就很容易理解,pVal传递进去的是变量的地址,cas通过这个来读取变量真实的值,oldVal传递的是变量在函数调用时的值,用来跟真实值进行比较,而newVal传递进去的是期望变量赋予的新的值。根据上面的cas的代码含义我们知道,当变量真实值不等于调用时的值的时候,是不会赋予变量新的值的。所以我们使用了一个WHILE来等待这个赋值成立。同时我们给与myValue一个volitale修饰,用意是让while中调用cas函数时,读取myValue的当前值,而不是寄存器中保存的值,以免变量值的“过期”,从而让这个cas可以在没有其他线程来修改myValue的时候执行成功,从而实现lock free的修改myValu