今天想学习一下ConcurrentHashMap 就顺便复习了下多线程的知识。凭记忆总结下
synchronized
注意它的监视器,当是代码块同步时一般是一个属性充当,当是一个方法块时这个方法所属的对象充当监视器
obj.wait()暂停当前线程的执行,进入阻塞状态,并释放琐(这点很重要)
obj.notify() 唤醒持有obj监视器琐的线程,进入就绪状态。注意这个方法执行并不是马上释放当前的琐,而是执行完当前的方法再使当前线程也进入继续状态与其他线程去竞争琐
ReentrantLock
这是Lock的一个实现类,当竞争不激烈的时用Lock保持同步反而会降低效率,synchronized是由底层的JVM实现互斥,因此效率会高一些。
但是在复杂的环境中(高并发,竞争琐激烈)用lock会更加效率高。ReentrantLock的功能比synchronized更多,比如定时获取某个琐,多个等待条件等。
死锁
两个线程互相等待对方施放琐,使程序无法继续执行。但也不会终止。
suspend方法很容易造成死锁
死锁的四个必要条件
互斥(Mutual exclusion):存在这样一种资源,它在某个时刻只能被分配给一个执行绪(也称为线程)使用;
持有(Hold and wait):当请求的资源已被占用从而导致执行绪阻塞时,资源占用者不但无需释放该资源,而且还可以继续请求更多资源;
不可剥夺(No preemption):执行绪获得到的互斥资源不可被强行剥夺,换句话说,只有资源占用者自己才能释放资源;
环形等待(Circular wait):若干执行绪以不同的次序获取互斥资源,从而形成环形等待的局面,想象在由多个执行绪组成的环形链中,每个执行绪都在等待下一个执行绪释放它持有的资源。
自己手打了一个消费生产者模式
1 //生产者 2 public class Producer implements Runnable{ 3 QueueList queue ; 4 Producer(QueueList q){ 5 this.queue = q; 6 } 7 @Override 8 public void run() { 9 for(int i=1;i<=30;i++){ 10 String index = "生产第"+i+"个"; 11 try { 12 queue.produce(index); 13 } catch (Exception e) { 14 e.printStackTrace(); 15 } 16 } 17 } 18 }
//消费者 public class Consumer implements Runnable{ QueueList queue ; Consumer(QueueList q){ this.queue = q; } @Override public void run() { for(int i=1;i<=30;i++){ String index = "消费第"+i+"个"; try { queue.consume(index); } catch (Exception e) { e.printStackTrace(); } } } }
//放产品的容器 public class QueueList { Object obj = new Object();//监视器 List<String> list = new ArrayList<String>(10);//放东西的工具,大小为10 public void consume(String index) throws Exception{ synchronized (obj) { //在代码块里同步 if(list.size()>0){ list.remove(list.size()-1); System.out.println(index); System.out.println("还剩"+list.size()+"个产品"); obj.notifyAll(); }else{ System.out.println("空了,等待。。。"); obj.wait(); } } } public void produce(String index) throws Exception{ synchronized (obj) { if(list.size()<10){ list.add(index); System.out.println(index); System.out.println("还可以生产"+(10-list.size())+"个产品"); obj.notifyAll(); }else{ System.out.println("满了,等待。。。"); obj.wait(); } } } }
public class Test { public static void main(String[] args) { QueueList q = new QueueList(); Producer pro = new Producer(q); Consumer con = new Consumer(q); Thread t1 = new Thread(pro); Thread t2 = new Thread(con); t1.start(); t2.start(); } }