Java 高并发基础

intro:读马士兵《Java高并发编程》记录
推荐http://www.cnblogs.com/andy-zhou/p/5339683.html

Java 高并发基础_第1张图片

JMM

synchronized

lambda

new Thread(()->t.m1(),"t1").start();
new Thread((t::m1,"t1").start();
new Thread(new Runnable(){
	@Override
	public void run(){
		t.m1();
	}
}).start();
  1. Synchronized(T.class){} 类似与 public synchronized static void
    m()注意静态方法不能锁this对象
  2. 执行有锁方法可以同时执行无锁方法;
  3. 业务读和业务写都要加锁,避免脏读(dirtyRead);
  4. synchronized获得的锁是可重入的;特殊情形:子类同步方法调用父类同步方法也可以
  5. 出现异常默认情况下锁会被释放,一定要try catch
  6. 简单程序模拟死锁
public void run(){  
    
  System.out.println(flag);  
  if(flag == 0){  
   synchronized(o1){  
    try{  
     Thread.sleep(500);  
    } catch(Exception e){  
     e.printStackTrace();  
    }  
    synchronized(o2){  
    }  
   }   
  }  
  if(flag == 1){  
   synchronized(o2){  
    try{  
     Thread.sleep(500);  
    } catch(Exception e){  
     e.printStackTrace();  
    }  
    synchronized(o1){  
    }  
   }   
  }   
 }  

voltile

volatile 不同线程间的内存(变量)可见性(理解为线程间通信,轻量级同步),但不能保证原子性(不如Synconized),但效率高,避免数据脏读

因为a=a+count(a++也是)包含了好几步操作,而此时多个线程的执行是无序的,因为没有任何机制来保证多个线程的执行有序性和原子性。volatile存在的意义是,任何线程对a的修改,都会马上被其他线程读取到,因为直接操作主存,没有线程对工作内存和主存的同步。所以,volatile的使用场景是有限的,在有限的一些情形下可以使用 volatile 变量替代锁。要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:1)对变量的写操作不依赖于当前值。2)该变量没有包含在具有其他变量的不变式中
比如说,a = 10;b = true ;不用加锁,赋值原子性,但是a++和b=!b需要。 这个时候可以用AtomicInteger(计算原子性和数据可见性),系统底层实现,用incrementAndGet去替代++;多个AtomicX之和不具有原子性,因为只保证递加是,但这段程序并不是,要用Synchronized程序段给方法业务逻辑中真正需要加锁的地方加锁,细粒度的锁优化速度

锁的对象发生改变,可以影响到需要之前锁的线程
不要以字符串常量作为锁

线程间通讯:
用wait-notify写很费劲
wait 释放锁,通常和while一起出现
notify 而不会释放锁,提醒处于wait状态的线程,观察者模式
notifyAll通知全体,生产消费要用,effect永远用notifyAll

sleep也不会释放锁
recommend:CountdownLatch

和Voltile相反,如果自己线程不想被别人知道,可以用:
ThreadLocal是空间换时间,即a和b线程各自保存一份;Synchronized是时间换空间,也就是a访问完b再来

ReentrantLock

  1. 手动上锁,手动解锁
  2. 可以根据tryLock的结果分别执行
  3. lockInterruptibly();去申请锁,但运行主线程来打断
  4. ReentrantLock(true);true表示公平锁,谁等的长谁拿lock
  5. NewCondition() await与signalAll可以精确指定

你可能感兴趣的:(java,#,JUC)