对于同步代码块,对于锁的操作是隐式的
但是在JDK1.5之前的这种方法效率有点低,判断会很多,后面升级之后有新的解决方案
jdk1.5以后将同步和锁封装成了对象,并将操作锁的隐式方式定义到了该对象中,将隐式动作变成了显示动作
Lock接口:替代了同步代码块或者同步函数,将同步的隐式锁操作变成显示锁操作,同时更为灵活,可以一个锁上加上多组监视器
lock():获取锁 unlock():释放锁,通常定义在finally代码块中
Condition接口:替代了Object中的wait notify notifyAll方法,将这些监视器方法单独封装,变成了Condition监视器对象,可以喝任意锁组合
await(); singal(); singalAll();
同步代码块到lock的变化:
1 import java.util.concurrent.locks.*;//lock在此包中 2 class LockDemo{ 3 public static void main(String[] args) { 4 Resrouce r = new Resrouce(); 5 Producer pro = new Producer(r); 6 Consumer con = new Consumer(r); 7 8 Thread t1 = new Thread(pro); 9 Thread t2 = new Thread(pro); 10 Thread t3 = new Thread(con); 11 Thread t4 = new Thread(con); 12 13 t1.start(); 14 t2.start(); 15 t3.start(); 16 t4.start(); 17 18 } 19 } 20 21 class Resrouce{ 22 private String name; 23 private int count = 1; 24 private boolean flag = false; 25 26 Lock lock = new ReentrantLock();//创建一个锁对象 27 28 public void set(String name){ 29 lock.lock(); 30 try{ 31 while(flag) 32 try{this.wait();}catch(Exception e){} 33 this.name = name+count; 34 count++; 35 System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name); 36 flag = true; 37 notifyAll(); 38 }finally{ 39 lock.unlock(); 40 } 41 42 } 43 44 public void out(){ 45 lock.lock(); 46 try{ 47 while(!flag) 48 try{this.wait();}catch(Exception e){} 49 System.out.println(Thread.currentThread().getName()+"...消费者.."+this.name); 50 flag = true; 51 notifyAll(); 52 }finally{ 53 lock.unlock(); 54 } 55 } 56 } 57 58 59 class Producer implements Runnable{ 60 private Resource r; 61 Producer(Resource r){ 62 this.r = r; 63 } 64 public void run(){ 65 while(true){ 66 r.set("烤鸭"); 67 } 68 } 69 } 70 71 72 class Consumer implements Runnable{ 73 private Resource r; 74 Consumer(Resource r){ 75 this.r = r; 76 } 77 public void run(){ 78 while(true){ 79 r.out(); 80 } 81 } 82 }
上述实例中锁换成了lock之后就不能用this来操作wait等方法了,应该用lock锁中的Condition接口中的方法,该接口将Object监视器方法(wait,notify,notifyAll)分解成不同的对象
1 import java.util.concurrent.locks.*; 2 class LockDemo{ 3 public static void main(String[] args) { 4 Resrouce r = new Resrouce(); 5 Producer pro = new Producer(r); 6 Consumer con = new Consumer(r); 7 8 Thread t1 = new Thread(pro); 9 Thread t2 = new Thread(pro); 10 Thread t3 = new Thread(con); 11 Thread t4 = new Thread(con); 12 13 t1.start(); 14 t2.start(); 15 t3.start(); 16 t4.start(); 17 18 } 19 } 20 21 class Resrouce{ 22 private String name; 23 private int count = 1; 24 private boolean flag = false; 25 26 Lock lock = new ReentrantLock(); 27 28 //通过已有的锁获取该锁上的监视器对象,一个锁可以有多个监视器 29 Condition con = lock.newCondition(); 30 31 public void set(String name){ 32 lock.lock(); 33 try{ 34 while(flag) 35 try{con.await();}catch(Exception e){} 36 this.name = name+count; 37 count++; 38 System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name); 39 flag = true; 40 con.signalAll(); 41 42 }finally{ 43 lock.unlock(); 44 } 45 } 46 47 public void out(){ 48 lock.lock(); 49 try{ 50 while(!flag) 51 try{con.await();}catch(Exception e){} 52 System.out.println(Thread.currentThread().getName()+"...消费者.."+this.name); 53 54 flag = true; 55 con.signalAll(); 56 }finally{ 57 lock.unlock(); 58 } 59 } 60 } 61 62 63 class Producer implements Runnable{ 64 private Resource r; 65 Producer(Resource r){ 66 this.r = r; 67 } 68 public void run(){ 69 while(true){ 70 r.set("烤鸭"); 71 } 72 } 73 } 74 75 76 class Consumer implements Runnable{ 77 private Resource r; 78 Consumer(Resource r){ 79 this.r = r; 80 } 81 public void run(){ 82 while(true){ 83 r.out(); 84 } 85 } 86 }
上述实例只有一组监视器,既监视着生产者,又监视着消费者,可以搞两个监视器,一组监视生产者,一组监视消费者
1 import java.util.concurrent.locks.*; 2 class LockDemo{ 3 public static void main(String[] args) { 4 Resrouce r = new Resrouce(); 5 Producer pro = new Producer(r); 6 Consumer con = new Consumer(r); 7 8 Thread t1 = new Thread(pro); 9 Thread t2 = new Thread(pro); 10 Thread t3 = new Thread(con); 11 Thread t4 = new Thread(con); 12 13 t1.start(); 14 t2.start(); 15 t3.start(); 16 t4.start(); 17 18 } 19 } 20 21 class Resrouce{ 22 private String name; 23 private int count = 1; 24 private boolean flag = false; 25 26 Lock lock = new ReentrantLock(); 27 28 /* 29 通过已有的锁获取该锁上的监视器对象,一个锁可以有多个监视器 30 Condition con = lock.newCondition(); 31 */ 32 33 //通过已有的锁获取监视器对象(两组),一组监视生产者,一组监视消费者 34 Condition Producer_con = lock.newCondition(); 35 Condition Consumer_con = lock.newCondition(); 36 public void set(String name){ 37 lock.lock(); 38 try{ 39 while(flag) 40 try{Producer_con.await();}catch(Exception e){} 41 this.name = name+count; 42 count++; 43 System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name); 44 flag = true; 45 //con.signalAll();//会发生死锁,所以要用到notifyAll 46 Consumer_con.signa();//有了两组监视器后就不用signaAll方法唤醒所有线程池中的线程了,只唤醒对方的一个线程,这样效率就高很多了 47 }finally{ 48 lock.unlock(); 49 } 50 } 51 52 public void out(){ 53 lock.lock(); 54 try{ 55 while(!flag) 56 try{Consumer_con.await();}catch(Exception e){} 57 System.out.println(Thread.currentThread().getName()+"...消费者.."+this.name); 58 59 flag = true; 60 //con.signalAll(); 61 62 Producer_con.signal(); 63 }finally{ 64 lock.unlock(); 65 } 66 } 67 } 68 69 70 class Producer implements Runnable{ 71 private Resource r; 72 Producer(Resource r){ 73 this.r = r; 74 } 75 public void run(){ 76 while(true){ 77 r.set("烤鸭"); 78 } 79 } 80 } 81 82 83 class Consumer implements Runnable{ 84 private Resource r; 85 Consumer(Resource r){ 86 this.r = r; 87 } 88 public void run(){ 89 while(true){ 90 r.out(); 91 } 92 } 93 }
wait和sleep的区别:
wait和sleep都是让线程处于冻结状态的方法
区别:
1.wait可以指定时间也可以不指定。sleep必须指定时间。
2.在同步中时,对CPU的执行权和锁的处理不同.wait:释放执行权,释放锁。sleep:释放执行权,不释放锁(不同中的代码必须拿到锁才能运行)
3.wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用(使用范围)
synchronized(x){
x.notify()
//或者wait()
}
4.sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常