并发同步:
1、wait方法用来使用线程等待某个条件,它必顺在同步块内部被调用,这个同步块通常会锁定当前对象实例
标准使用方式:
synchronized(this){
while(condition){
if(condition){
try{
object.wait;
......
}catch(exception e){
}
}else{
notifyall;
}
}
}
或
do{
synchronized(this){
if(condition){
try{
object.wait;
......
}catch(exception e){
}
}else{
notifyall;
}
}
}while(condition);
2、始终使用wait循环来调用wait方法,永远不要要循环之外调用wait方法。这样做的原因是尽管并不满足被唤醒条件,但是由于其他线程调用notifyall()方法会导致被阻塞线程意外唤醒,些时执行条件并不满足,它将破坏被锁保护的约定关系,导致约束失效,引起意想不到的结果。
3、唤醒
当多个线程共享同一个变量的时候,每个读或写数据的操作方法都必顺加锁进行同步。
volatile
当一个变量被volatile修饰后,它将具备以下两种物性
1、线程可见性:当一个线程修改了被volatile修饰的变量后,无论加锁与否,其它线程都可以立即看到最新的修改,而普通变量却做不到。
2、禁止指令重排优化:普通变量仅仅保证在该方法的执行过程中所有依赖赋值结果的地方都能获取正确的结果,而不能侦查证变量赋值操作的顺序和程序代码执行顺序一致。
pubic class test{
public static void main(string[] agrs){
public boolean stop;
Thread nt = new Thread(new Runnable(){
public void run(){
while(!stop){
}
}
});
nt.start();
stop = true;
}
}
优化重排后
if(!stop){
while(true){
}
}
volatile仅仅解决了可见性的问题,但是它并不能保证互斥性,也就是说多个线程并发修改某个变量时,仍旧会产生多线程问题,不能靠volatie来完全代替传统的锁.
volatile最适合使用的是一个线程写,其他线程读的场合,如果有多个线程并发写操作,仍然需要使用锁或者线程安全的容器或者原子变量来代替。
互斥同步最主要的问题就是进行线程阻塞和唤醒所带来的性能额外损耗,因此这种同步被称为阻塞同步,是一种悲观的并发策略,悲观锁。
乐观锁就是先进行操作,操作完成之后再判断操作是否成功,是否有并发问题,如果有则进行失败补偿,如果没有就算操作成功,非阻塞同步.
java中应用最广泛的非阻塞同步就是CAS。