首页 > 编程 > Java > 正文

Java编程之多线程死锁与线程间通信简单实现代码

2019-11-26 11:04:53
字体:
来源:转载
供稿:网友

死锁定义

死锁是指两个或者多个线程被永久阻塞的一种局面,产生的前提是要有两个或两个以上的线程,并且来操作两个或者多个以上的共同资源;我的理解是用两个线程来举例,现有线程A和B同时操作两个共同资源a和b,A操作a的时候上锁LockA,继续执行的时候,A还需要LockB进行下面的操作,这个时候b资源在被B线程操作,刚好被上了锁LockB,假如此时线程B刚好释放了LockB则没有问题,但没有释放LockB锁的时候,线程A和B形成了对LockB锁资源的争夺,从而造成阻塞,形成死锁;具体其死锁代码如下:

public class MyDeadLockTest { public static void main(String[] args){  Object obj1 = new Object();  Thread thread1 = new Thread(new DeadRes(true,obj1));  Thread thread2 = new Thread(new DeadRes(false,obj1));  thread1.start();  thread2.start(); }}class DeadRes implements Runnable{ boolean flag; Object obj; public DeadRes(boolean flag, Object obj1) {  this.flag = flag;  this.obj = obj1; } @Override public void run() {   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-1 acquie lock is objThread-0 acquie lock is DeadRes.class

当然每次执行的结果不一样,有可能是一种和谐状态,没有发生死锁,此时为保证每次死锁,可以让run()方法中,执行while(true)循环,这样保证了每次必定发生死锁;当然实际应用中,我们应该尽量避免死锁,当有多线程操作多个共同资源的时候,避免发生同一锁对象的同步嵌套。

线程间的通讯―-生产者与消费者模式

1、让两个线程交替进行操作,当生产了一个数字后,紧接着消费一个,首先采用Object对象中的wait-notify来实现,具体代码如下:

public class ThreadProConsume { public static void main(String[] args){  Product product = new Product();  Thread thread1 = new Thread(new Producer(product));  Thread thread2 = new Thread(new Consumer(product));  thread1.start();  thread2.start(); }}class Product{ String name; private int count = 1; boolean flag = false; public synchronized void set(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(); } public synchronized void out(){  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; public Producer(Product product) {  this.res = product; } @Override public void run() {  while(true){   res.set("guyue");  } }}class Consumer implements Runnable{ Product res; public Consumer(Product product) {  this.res = product; } @Override public void run() {  while(true){   res.out();  } }}

执行结果如图:

Thread-1 consume num is : guyue--3938Thread-0 produce num : guyue--3939Thread-1 consume num is : guyue--3939Thread-0 produce num : guyue--3940Thread-1 consume num is : guyue--3940Thread-0 produce num : guyue--3941Thread-1 consume num is : guyue--3941

当超过两个以上线程操作的时候,这里需要在set()与out()方法中的if判断改为while,并且notif方法,改为notifyAll(),这样多个线程操作的时候,便可以交替进行,具体代码如下:

public class ThreadProConsume { public static void main(String[] args){  Product product = new Product();  Thread thread1 = new Thread(new Producer(product));  Thread thread3 = new Thread(new Producer(product));  Thread thread2 = new Thread(new Consumer(product));  Thread thread4 = new Thread(new Consumer(product));  thread1.start();  thread3.start();  thread2.start();  thread4.start(); }}class Product{ String name; private int count = 1; boolean flag = false; public synchronized void 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(); } public synchronized void 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-0 produce num : guyue--50325Thread-2 consume num is : guyue--50325Thread-1 produce num : guyue--50326Thread-3 consume num is : guyue--50326Thread-0 produce num : guyue--50327Thread-2 consume num is : guyue--50327Thread-1 produce num : guyue--50328Thread-3 consume num is : guyue--50328

2、采用Lock-Condition方法实现如下:

class Product{ String name; private int count = 1; boolean flag = false; Lock lock = new ReentrantLock(); 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-0 produce num : guyue--20305Thread-3 consumer num is : guyue--20305Thread-1 produce num : guyue--20306Thread-2 consumer num is : guyue--20306Thread-0 produce num : guyue--20307Thread-3 consumer num is : guyue--20307Thread-1 produce num : guyue--20308Thread-2 consumer num is : guyue--20308

以上就是本文关于Java编程之多线程死锁与线程间通信简单实现代码的全部内容,希望对大家有所帮助。关于Java多线程以及线程间通信的例子,本站还有几篇文章可以参考:

详解java中的互斥锁信号量和多线程等待机制Java多线程编程小实例模拟停车场系统Java网络编程基础篇之单向通信

如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表