死锁定义 死锁是指两个或者多个线程被永久阻塞的一种局面,产生的前提是要有两个或两个以上的线程,并且来操作两个或者多个以上的共同资源;我的理解是用两个线程来举例,现有线程 A 和 B 同时操作两个共同资源 a 和 b,A 操作 a 的时候上锁 LockA, 继续执行的时候,A 还需要 LockB 进行下面的操作,这个时候 b 资源在被 B 线程操作,刚好被上了锁 LockB,假如此时线程 B 刚好释放了 LockB 则没有问题,但没有释放 LockB 锁的时候,线程 A 和 B 形成了对 LockB 锁资源的争夺,从而造成阻塞,形成死锁;具体其死锁代码如下:
- public class MyDeadLockTest{
- public static voidmain(String[] args){
- Object obj1 =newObject();
- Thread thread1 =newThread(newDeadRes(true,obj1));
- Thread thread2 =newThread(newDeadRes(false,obj1));
- thread1.start();
- thread2.start();
- }
- }class DeadRes implements Runnable{
- booleanflag;
- Object obj;publicDeadRes(booleanflag, Object obj1) {this.flag = flag;this.obj = obj1;
- }
- @Overridepublic voidrun() {if(flag){
- synchronized (DeadRes.class){
- System.out.println(Thread.currentThread().getName()+" acquie lock is DeadRes.class");
- synchronized (obj){
- System.out.println(Thread.currentThread().getName()+" acquie lock is obj");
- }
- }
- }else{
- synchronized (obj){
- System.out.println(Thread.currentThread().getName()+" acquie lock is obj");
- synchronized (DeadRes.class){
- System.out.println(Thread.currentThread().getName()+" acquie lock is DeadRes.class");
- }
- }
- }
- }
- }
执行结果如下图:
- Thread-1acquielock isobj
- Thread-0acquielock isDeadRes.class
当然每次执行的结果不一样,有可能是一种和谐状态,没有发生死锁,此时为保证每次死锁,可以让 run() 方法中,执行 while(true) 循环,这样保证了每次必定发生死锁;当然实际应用中,我们应该尽量避免死锁,当有多线程操作多个共同资源的时候,避免发生同一锁对象的同步嵌套。
线程间的通讯—- 生产者与消费者模式 1、让两个线程交替进行操作,当生产了一个数字后,紧接着消费一个,首先采用 Object 对象中的 wait-notify 来实现,具体代码如下:
- public class ThreadProConsume{
- public static voidmain(String[] args){
- Product product =newProduct();
- Thread thread1 =newThread(newProducer(product));
- Thread thread2 =newThread(newConsumer(product));
- thread1.start();
- thread2.start();
- }
- }class Product{String name;private int count=1;booleanflag =false;publicsynchronizedvoidset(String name){if(flag){try{this.wait();
- }catch(InterruptedException e) {
- e.printStackTrace();
- }
- }this.name = name +"--"+count++;
- flag =true;
- System.out.println(Thread.currentThread().getName()+" produce num : "+this.name);this.notify();
- }publicsynchronizedvoidout(){if(!flag){try{this.wait();
- }catch(InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.println(Thread.currentThread().getName()+" consume num is : "+this.name);
- flag =false;this.notify();
- }
- }class Producer implements Runnable{Product res;publicProducer(Product product) {this.res = product;
- }
- @Overridepublic voidrun() {while(true){
- res.set("guyue");
- }
- }
- }class Consumer implements Runnable{Product res;publicConsumer(Product product) {this.res = product;
- }
- @Overridepublic voidrun() {while(true){
- res.out();
- }
- }
- }
执行结果如图:
- Thread-1consumenumis : guyue--3938Thread-0producenum: guyue--3939Thread-1consumenumis : guyue--3939Thread-0producenum: guyue--3940Thread-1consumenumis : guyue--3940Thread-0producenum: guyue--3941Thread-1consumenumis : guyue--3941
当超过两个以上线程操作的时候,这里需要在 set() 与 out() 方法中的 if 判断改为 while,并且 notif 方法,改为 notifyAll(),这样多个线程操作的时候,便可以交替进行,具体代码如下:
- public classThreadProConsume {public static void main(String[] args){
- Product product =newProduct();
- Thread thread1 =newThread(newProducer(product));
- Thread thread3 =newThread(newProducer(product));
- Thread thread2 =newThread(newConsumer(product));
- Thread thread4 =newThread(newConsumer(product));
- thread1.start();
- thread3.start();
- thread2.start();
- thread4.start();
- }
- }
- class Product{
- String name;private intcount =1;
- boolean flag =false;publicsynchronizedvoid set(String name){while(flag){try{this.wait();
- }catch(InterruptedException e) {
- e.printStackTrace();
- }
- }this.name = name +"--"+count++;
- flag =true;
- System.out.println(Thread.currentThread().getName()+" produce num : "+this.name);this.notifyAll();
- }publicsynchronizedvoid out(){while(!flag){try{this.wait();
- }catch(InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.println(Thread.currentThread().getName()+" consume num is : "+this.name);
- flag =false;this.notifyAll();
- }
- }
执行结果如下:
- Thread-0producenum: guyue--50325Thread-2consumenumis : guyue--50325Thread-1producenum: guyue--50326Thread-3consumenumis : guyue--50326Thread-0producenum: guyue--50327Thread-2consumenumis : guyue--50327Thread-1producenum: guyue--50328Thread-3consumenumis : guyue--50328
2、采用 Lock-Condition 方法实现如下:
- class Product{
- String name;private intcount =1;
- boolean flag =false;
- Locklock=newReentrantLock();
- Condition conditon =lock.newCondition();public void set(String name){try{lock.lock();while(flag){
- conditon.await();
- }this.name = name +"--"+count++;
- flag =true;
- System.out.println(Thread.currentThread().getName()+" produce num : "+this.name);
- conditon.signalAll();
- }catch(Exception e){
- }finally{lock.unlock();
- }
- }public void out(){try{lock.lock();while(!flag){
- conditon.await();
- }
- flag =false;
- System.out.println(Thread.currentThread().getName()+" consumer num is : "+this.name);
- conditon.signalAll();
- }catch(Exception e){
- }finally{lock.unlock();
- }
- }
- }
执行结果如下:
- Thread-0producenum: guyue--20305Thread-3consumernumis : guyue--20305Thread-1producenum: guyue--20306Thread-2consumernumis : guyue--20306Thread-0producenum: guyue--20307Thread-3consumernumis : guyue--20307Thread-1producenum: guyue--20308Thread-2consumernumis : guyue--20308
来源: http://blog.csdn.net/yongxihu/article/details/70277372