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

死锁定义

死锁是指两个或者多个线程被永久阻塞的一种局面,产生的前提是要有两个或两个以上的线程,并且来操作两个或者多个以上的共同资源;我的理解是用两个线程来举例,现有线程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 obj
Thread-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--3938
Thread-0 produce num : guyue--3939
Thread-1 consume num is : guyue--3939
Thread-0 produce num : guyue--3940
Thread-1 consume num is : guyue--3940
Thread-0 produce num : guyue--3941
Thread-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--50325
Thread-2 consume num is : guyue--50325
Thread-1 produce num : guyue--50326
Thread-3 consume num is : guyue--50326
Thread-0 produce num : guyue--50327
Thread-2 consume num is : guyue--50327
Thread-1 produce num : guyue--50328
Thread-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--20305
Thread-3 consumer num is : guyue--20305
Thread-1 produce num : guyue--20306
Thread-2 consumer num is : guyue--20306
Thread-0 produce num : guyue--20307
Thread-3 consumer num is : guyue--20307
Thread-1 produce num : guyue--20308
Thread-2 consumer num is : guyue--20308

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

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

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

(0)

相关推荐

  • 简单谈谈RxJava和多线程并发

    前言 相信对于RxJava,大家应该都很熟悉,他最核心的两个字就是异步,诚然,它对异步的处理非常的出色,但是异步绝对不等于并发,更不等于线程安全,如果把这几个概念搞混了,错误的使用RxJava,是会来带非常多的问题的. RxJava与并发 首先让我们来看一段RxJava协议的原文: Observables must issue notifications to observers serially (not in parallel). They may issue these notificat

  • java实现多线程之定时器任务

    在Java中Timer是java.util包中的一个工具类,提供了定时器的功能.我们可以创建一个Timer对象,然后调用其schedule方法在某个特定的时间去执行一个特定的任务.并且你可以让其以特定频率一直执行某个任务,这个任务是用TimerTask来描述的,我们只需要将要进行的操作写在TimerTask类的run方法中即可.先附上两个小例子一遍让读者了解什么是定时器.接着再分析其中的一些源码实现. 第一个小例子: package com.zkn.newlearn.thread; import

  • Java多线程下载文件实例详解

    本文实例为大家分享了Java多线程下载文件的具体代码,供大家参考,具体内容如下 import java.io.File; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class MulThreadDownload { public static void main(String[] args)

  • Java 多线程有序执行的几种方法总结

    Java 多线程有序执行的几种方法总结 同事无意间提出了这个问题,亲自实践了两种方法.当然肯定还会有更多更好的方法. 方法一 import java.util.concurrent.atomic.AtomicInteger; public class OrderedThread1 { static AtomicInteger count = new AtomicInteger(0); public static void main(String[] args) throws Interrupte

  • Java实现多线程文件下载的代码示例

    Java实现多线程文件下载思路: 1.基本思路是将文件分段切割.分段传输.分段保存. 2.分段切割用到HttpUrlConnection对象的setRequestProperty("Range", "bytes=" + start + "-" + end)方法. 3.分段传输用到HttpUrlConnection对象的getInputStream()方法. 4.分段保存用到RandomAccessFile的seek(int start)方法. 5

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

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

  • Java编程线程间通信与信号量代码示例

    1.信号量Semaphore 先说说Semaphore,Semaphore可以控制某个资源可被同时访问的个数,通过acquire()获取一个许可,如果没有就等待,而release()释放一个许可.一般用于控制并发线程数,及线程间互斥.另外重入锁ReentrantLock也可以实现该功能,但实现上要复杂些. 功能就类似厕所有5个坑,假如有10个人要上厕所,那么同时只能有多少个人去上厕所呢?同时只能有5个人能够占用,当5个人中的任何一个人让开后,其中等待的另外5个人中又有一个人可以占用了.另外等待的

  • Java通过wait()和notifyAll()方法实现线程间通信

    本文实例为大家分享了Java实现线程间通信的具体代码,供大家参考,具体内容如下 Java代码(使用了2个内部类): package Threads; import java.util.LinkedList; /** * Created by Frank */ public class ProdCons { protected LinkedList<Object> list = new LinkedList<>(); protected int max; protected bool

  • Java使用wait/notify实现线程间通信上篇

    线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一,使用线程间进行通信后,系统之间的交互性会更强大,大大提高CPU利用率. 等待/通知机制 (1)不使用等待/通知机制实现线程间通信 样例代码如下: public class TestC2 { public static void main(String[] args) throws Exception { MyList myList = new MyList(); ThreadA

  • java多线程编程学习(线程间通信)

    一.概要 线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就是成为整体的必用方案之一.可以说,使线程进行通信后,系统之间的交互性会更强大,在大大提高cpu利用率的同时还会使程序员对各线程任务在处理过程中进行有效的把控和监督. 二.等待/通知机制 1."wait/notify"机制:等待/通知机制,wait使线程暂停运行,而notify 使暂停的线程继续运行.用一个厨师和服务员的交互来说明: (1) 服务员取到菜的时间取决于厨师,所以服务员就有&

  • Python多线程编程(八):使用Event实现线程间通信

    使用threading.Event可以实现线程间相互通信,之前的Python:使用threading模块实现多线程编程七[使用Condition实现复杂同步]我们已经初步实现了线程间通信的基本功能,但是更为通用的一种做法是使用threading.Event对象.使用threading.Event可以使一个线程等待其他线程的通知,我们把这个Event传递到线程对象中,Event默认内置了一个标志,初始值为False.一旦该线程通过wait()方法进入等待状态,直到另一个线程调用该Event的set

  • java线程间通信的通俗解释及代码示例

    线程间通信:由于多线程共享地址空间和数据空间,所以多个线程间的通信是一个线程的数据可以直接提供给其他线程使用,而不必通过操作系统(也就是内核的调度). 进程间的通信则不同,它的数据空间的独立性决定了它的通信相对比较复杂,需要通过操作系统.以前进程间的通信只能是单机版的,现在操作系统都继承了基于套接字(socket)的进程间的通信机制.这样进程间的通信就不局限于单台计算机了,实现了网络通信.线程通信主要分为以下几个部分,下面通过生活中图书馆借书的例子简单讲解以下: 通过共享对象通信 加入图书馆只有

  • 浅谈Java线程间通信之wait/notify

    Java中的wait/notify/notifyAll可用来实现线程间通信,是Object类的方法,这三个方法都是native方法,是平台相关的,常用来实现生产者/消费者模式.先来我们来看下相关定义: wait() :调用该方法的线程进入WATTING状态,只有等待另外线程的通知或中断才会返回,调用wait()方法后,会释放对象的锁. wait(long):超时等待最多long毫秒,如果没有通知就超时返回. notify() :通知一个在对象上等待的线程,使其从wait()方法返回,而返回的前提

  • 深入解析Java的线程同步以及线程间通信

    Java线程同步 当两个或两个以上的线程需要共享资源,它们需要某种方法来确定资源在某一刻仅被一个线程占用.达到此目的的过程叫做同步(synchronization).像你所看到的,Java为此提供了独特的,语言水平上的支持. 同步的关键是管程(也叫信号量semaphore)的概念.管程是一个互斥独占锁定的对象,或称互斥体(mutex).在给定的时间,仅有一个线程可以获得管程.当一个线程需要锁定,它必须进入管程.所有其他的试图进入已经锁定的管程的线程必须挂起直到第一个线程退出管程.这些其他的线程被

  • Java编程中实现Condition控制线程通信

    java中控制线程通信的方法 1.传统的方式:利用synchronized关键字来保证同步,结合wait(),notify(),notifyAll()控制线程通信.不灵活. 2.利用Condition控制线程通信,灵活. 3.利用管道pipe进行线程通信,不推荐 4.利用BlockingQueue控制线程通信 本文就讲解利用Condition控制线程通信,非常灵活的方式. Condition类是用来保持Lock对象的协调调用. 对Lock不了解的可以参考:Java线程同步Lock同步锁代码示例

随机推荐