java 7 并发 初级 学习记录(3)
2014-06-27 00:00
162 查看
1.Lock
另一种同步方式,显示地在代码中使用lock()方法,指明在此处进行加锁了,当然还有unlock()方法,指明在此处解锁。Lock的使用比synchronized同步块更加灵活,但也更容易出错,使用不当就会发生死锁,所以要非常小心。
Lock是一个接口,一般使用它的某些实现类如最常用的ReentrantLock,参考如下代码:
lock还有一个tryLock()的方法,它的意思是,尝试着去获取锁,如果获取了,返回true,如果已经被别的线程占用了,则返回false。注意的是,它不会等待,也就是说不管有没有获取锁,它都会立刻返回结果,并且向下执行,不会被堵塞。如果线程获取了锁,那么在执行完毕之前必须调用unlock()解锁,不然线程会永远堵塞。
2.死锁
当两个线程在获得各自锁,还没有解锁的情况下,相互试图获取对方的锁,这样就会造成死锁!双方都在等待对方先解锁。
可见在thread0获取lock2的锁,同时thread2获取lock1的锁之后,发生了死锁。
3.Condition
有没有想过Lock中如何使用wait,notify,notifyall?lock有一个newCondition()方法,返回一个Condition对象,这个对象的功能有点类似于同步块中的参数对象。可以使用condition中的await(),signal(),signalAll()来代替。下面来改写第二片中最后一个例子:其他类不用变,需要修改Target类
Lock还有其他一些实现类可以提供给我们使用,具体使用也是类似,可自行参考其他资料。
另一种同步方式,显示地在代码中使用lock()方法,指明在此处进行加锁了,当然还有unlock()方法,指明在此处解锁。Lock的使用比synchronized同步块更加灵活,但也更容易出错,使用不当就会发生死锁,所以要非常小心。
Lock是一个接口,一般使用它的某些实现类如最常用的ReentrantLock,参考如下代码:
public class Target { private Lock lock = new ReentrantLock(); public void testLock(){ System.out.println(Thread.currentThread().getName() + " 进入testLock方法"); lock.lock(); System.out.println(Thread.currentThread().getName() + " 获取锁"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 执行完毕,准备解锁"); lock.unlock(); } } ---------------------------------------------------------------------------------------------- public class JavaCurrent { public static void main(String[] args) { Target target = new Target(); for (int i = 0; i < 5; i++) { Thread t = new Thread(new Task(target)); t.start(); } } } class Task implements Runnable{ private Target target; public Task(Target target) { this.target = target; } @Override public void run() { target.testLock(); } } 执行结果: Thread-0 进入testLock方法 Thread-0 获取锁 Thread-3 进入testLock方法 Thread-1 进入testLock方法 Thread-2 进入testLock方法 Thread-4 进入testLock方法 Thread-0 执行完毕,准备解锁 Thread-3 获取锁 Thread-3 执行完毕,准备解锁 Thread-1 获取锁 Thread-1 执行完毕,准备解锁 Thread-2 获取锁 Thread-2 执行完毕,准备解锁 Thread-4 获取锁 Thread-4 执行完毕,准备解锁
lock还有一个tryLock()的方法,它的意思是,尝试着去获取锁,如果获取了,返回true,如果已经被别的线程占用了,则返回false。注意的是,它不会等待,也就是说不管有没有获取锁,它都会立刻返回结果,并且向下执行,不会被堵塞。如果线程获取了锁,那么在执行完毕之前必须调用unlock()解锁,不然线程会永远堵塞。
2.死锁
当两个线程在获得各自锁,还没有解锁的情况下,相互试图获取对方的锁,这样就会造成死锁!双方都在等待对方先解锁。
public class DeadLock { private Lock lock1 = new ReentrantLock(); private Lock lock2 = new ReentrantLock(); public void testDeadLock1(){ System.out.println(Thread.currentThread().getName() + "进入testDeadLock1方法"); lock1.lock();//先让线程使用lock1加锁 System.out.println(Thread.currentThread().getName() + "获取lock1锁"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } lock2.lock(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } lock2.unlock(); System.out.println(Thread.currentThread().getName() + "lock1解锁"); lock1.unlock(); } public vo 3ff0 id testDeadLock2(){ System.out.println(Thread.currentThread().getName() + "进入testDeadLock2方法"); lock2.lock();//先让线程使用lock1加锁 System.out.println(Thread.currentThread().getName() + "获取lock2锁"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } lock1.lock(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } lock1.unlock(); System.out.println(Thread.currentThread().getName() + "lock2解锁"); lock2.unlock(); } } --------------------------------------------------------------------------------------- public class JavaCurrent { public static void main(String[] args) { DeadLock target = new DeadLock(); for (int i = 0; i < 5; i++) { Thread t = new Thread(new Task1(target)); t.start(); } } } class Task1 implements Runnable{ private DeadLock deadLock; public Task1(DeadLock deadLock) { this.deadLock = deadLock; } @Override public void run() { deadLock.testDeadLock1(); deadLock.testDeadLock2(); } } 运行结果: Thread-0进入testDeadLock1方法 Thread-2进入testDeadLock1方法 Thread-1进入testDeadLock1方法 Thread-4进入testDeadLock1方法 Thread-3进入testDeadLock1方法 Thread-0获取lock1锁 Thread-0lock1解锁 Thread-0进入testDeadLock2方法 Thread-0获取lock2锁 Thread-2获取lock1锁
可见在thread0获取lock2的锁,同时thread2获取lock1的锁之后,发生了死锁。
3.Condition
有没有想过Lock中如何使用wait,notify,notifyall?lock有一个newCondition()方法,返回一个Condition对象,这个对象的功能有点类似于同步块中的参数对象。可以使用condition中的await(),signal(),signalAll()来代替。下面来改写第二片中最后一个例子:其他类不用变,需要修改Target类
public class Target { private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); private int allowIn = 3;//允许3个线程经过setwait() private int count = 0; public void setWait(){ System.out.println(Thread.currentThread().getName()+ " 进入setWait"); lock.lock(); System.out.println(Thread.currentThread().getName()+ " 进入setWait中的同步块中"); if(count > allowIn){ try { System.out.println(Thread.currentThread().getName()+ " 发现已经超出最大数值了,只能等待了!"); condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } try { TimeUnit.SECONDS.sleep(1);//休眠1秒 System.out.println(Thread.currentThread().getName()+ " 处理setWait完毕,退出方法,释放锁"); count ++ ; } catch (InterruptedException e) { e.printStackTrace(); }finally{ lock.unlock(); } } public void setNotify(){ System.out.println(Thread.currentThread().getName()+ " 进入setNotify"); lock.lock(); System.out.println(Thread.currentThread().getName()+ " 进入setNotify中的同步块中"); if(count > allowIn){ System.out.println(Thread.currentThread().getName()+ " 发现已经超出最大数值了,数值清理!"); count = 0; condition.signalAll(); }else{ try { TimeUnit.SECONDS.sleep(2);//休眠2秒 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+ " 处理setNotify完毕,退出方法,释放锁"); } lock.unlock(); } } 运行结果和原来的例子基本一致。
Lock还有其他一些实现类可以提供给我们使用,具体使用也是类似,可自行参考其他资料。
相关文章推荐
- java 7 并发 初级 学习记录(1)
- java 7 并发 初级 学习记录(2)
- Head First Java (第二版)学习记录 5 - 编写程序 DotCom 初级游戏
- java高并发学习记录-死锁,活锁,饥饿
- Java并发编程学习记录#1
- Java并发编程学习记录#4
- java并发集合框架学习记录
- 【学习记录】Java初级
- Java并发编程学习记录#2
- Java Media Framework 基础教程(学习JMF中,看到好的中文教程,在这里记录下来)
- 学习记录——【转】java中打开explorer
- Java5 并发学习
- 从今天起开始涉足java的学习,记录学习的点滴
- Java并发学习笔记
- 8月21号,决定入住CSDN,不定期的更新Blog,记录本人JAVA学习之路
- java学习记录
- 课堂笔记学习java(初级)第三节课
- 课堂笔记学习java(初级)第二节课
- 记录学习Java的心得和生活,开心Java今日特开博!
- 网上一篇关于JavaScript基本概念初级讲解论坛贴的学习记录