Java多线程设计的并发控制

并发级别:
    阻塞:悲观控制策略,试图进入临界区前,获取锁,得不到,线程挂起。
    无饥饿:锁是公平的,满足先来后到,进行排队。
    无障碍:乐观控制策略,线程在操作前,先读取并保存一个“一致性标记”,在操作完成后,再次读取,检查这个标记是否被更改过,如果两者一致,说明资源没有冲突,如果不一致,说明资源可能在操作过程与其他写线程冲突,需要重试操作,而任何对资源有修改操作的线程,在修改数据前,都需要更新这个一致标记,表示数据不再安全。 
    无锁:无锁的并行都是无障碍的,在无锁的情况下,所有的线程都能尝试对临界区进行访问,但不同的是,无锁的并发保证必然有一个线程能够在有限步内完成操作离开临界区。在无锁的调用中,一个典型的特点是可能会包含一个无穷循环,在循环中,线程会不断尝试修改共享变量,如果没有冲突,修改成功,退出,否则继续尝试修改。while(!atomicVar.compareAndSet(localVar, localVar+1)){localVar = atomicVar.get();} 
    无等待:一个典型的无等待就是RCU,对数据的读可以不加控制,因此所有的读线程都是无等待的,不会被锁定,也不会引起任何冲突,在写数据的时候,先取得原始数据的副本,接着只修改副本数据,修改完成后,在合适的时机回写数据。 
    JAVA内存模型(JMM)围绕着并发编程中的原子性,内存可见性,有序性建立,定义了程序中变量访问的规则。volatile保证变量值修改后的新值立刻同步到主存,每次使用变量前立即从主存中刷新,从而保证了线程间volatile变量的内存可见性。synchronized、Lock、final也可以保证内存可见性。
1,synchronized 
    指定加锁对象:对给定对象加锁,进入同步代码前工获取给定对象的锁 
     直接作用于实例方法:对当前实例对象加锁 
     直接作用于静态方法:对当前类加锁 
     可重入,不可中断,非公平
2,重入锁(ReentrantLock) 
     可重入,可中断,可超时等待,可无等待,可实现公平、非公平的锁 
     重要方法: 
     lock(),lockInterruptibly(),tryLock(),tryLock(long time, TimeUnit unit),unlock()
3,条件变量 
     通过Lock接口的newCondition方法生成一个与当前重入锁绑定的Condition实例。 
     重要方法: 
     void await(),void awatUninterruptibly(),long awatiNanos(long nanosTimeout), 
     boolean awati(long time, TimeUnit unit), void signal(),void signalAll()
4,信号量 
     允许多线程获得访问许可。 
     public Semaphore(int permits) 
     public Semaphore(int permits, boolean fair) 
     public void acquire() 
     public void acquireUninterruptibly() 
     public void tryAcquire() 
     public void tryAcquire(long time, TimeUnit unit) 
     public void release()
5,读写锁 
     ReentrantReadWriteLock rwLock = new  ReentrantReadWriteLock(); 
     Lock rlock = rwLock.readLock(); 
     Lock wlock = rwLock.writeLock(); 

6,原子类

    AtomicInteger、AtomicLong、AtomicBoolean、AtomicReference、AtomicStampedReference、AtomicIntegerArray、AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater
7,锁优化

    减少锁持有时间,减少锁粒度,读写分离锁替换独占锁,锁分离,锁粗化。

    Java虚拟机对锁优化策略:

    锁偏向:对加锁操作的优化,如果一个线程获得了锁,那么锁就进入偏向模式,当这个线程再次请求锁时,无须做任何同步操作,对于没有锁竞争的场合,偏向锁有比较好的优化效果;锁竞争比较激烈的场合,最有可能的是每次不同的线程请求相同的锁,偏向模式失效。使用-XX:+UseBiasedLocking开启

    轻量级锁:在偏向锁失败时,虚拟机使用轻量级锁优化,它只是简单将对象头部作为指针,指向持有锁的线程堆栈的内部,来判断一个线程是否持有对象锁,轻量级锁失败,升级为重量级锁。

    自旋锁:虚拟机为避免线程真实地在操作系统层面挂起,让当前线程做几个空循环,在经过若干次循环后,如果得到锁,进入临界区,失败,线程挂起。

    锁清除:在JIT编译时,对运行上下文的扫描,通过逃逸分析技术,观察某个变量是否会逃出一个作用域,去除不可能存在共享资源竞争的锁。-XX:+DoEscapeAnalysis打开逃逸分析,-XX:+EliminateLocks打开锁清除。

   

猜你喜欢

转载自leilianjie.iteye.com/blog/2314611