死锁:

同步嵌套同步,而且使用的锁不是同一把锁时就可能出现死锁

class Test implements Runnable
{
private boolean flag;
Test(boolean flag)
{
this.flag = flag;
} public void run()
{
if(flag)
{
while(true)
{
synchronized(MyLock.locka)
{
System.out.println(Thread.currentThread().getName()+"...if locka ");
synchronized(MyLock.lockb)
{
System.out.println(Thread.currentThread().getName()+"..if lockb");
}
}
}
}
else
{
while(true)
{
synchronized(MyLock.lockb)
{
System.out.println(Thread.currentThread().getName()+"..else lockb");
synchronized(MyLock.locka)
{
System.out.println(Thread.currentThread().getName()+".....else locka");
}
}
}
}
}
} class MyLock
{
static Object locka = new Object();
static Object lockb = new Object();
} class DeadLockTest
{
public static void main(String[] args)
{
Thread t1 = new Thread(new Test(true));
Thread t2 = new Thread(new Test(false));
t1.start();
t2.start();
}
}

线程间通讯:

其实就是多线程操作同一个资源,但是操作的动作不同。

例,用多线程操作生成一个人名+性别(男的用英文表示,女的用中文表示),然后打印。

class Res
{
String name;
String sex;
} class Input implements Runnable
{
private Res r;
Input(Res r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized(r)
{
if (x==0)
{
r.name = "Mike";
r.sex="man";
}
else
{
r.name = "丽丽";
r.sex="女";
}
}
x = (x+1)%2;
}
}
} class Output implements Runnable
{
private Res r;
Output(Res r)
{
this.r = r;
}
public void run()
{
while(true)
{
synchronized(r)
{
System.out.println(r.name + "..." +r.sex);
}
}
}
} class ThreadCommunication
{
public static void main(String[] args)
{
Res r = new Res();
Input in = new Input(r);
Output out = new Output(r); Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}

注意:1,操作的共同资源必须上锁;2,使用的锁在内存中一定要保证是唯一的;

在上个例子中,并不是按照我们期待的那样,生成一个对象然后打印该对象,即输入一个就输出一个,这就需要用到等待-唤醒机制。

等待-唤醒:

wait:

notify:

notifyall:

都使用在同步中,因为要对持有监视器(锁)的线程操作,所以使用在同步中,因为只有同步才具有锁。

为什么这些操作线程的方法,要定义在Object类中呢?以为你这些方法在操作同步中线程时,都必须要表示它们所操作线程持有的锁。只有同一个锁上的被等待线程可以被同一个锁上的notify唤醒,不可以对不同锁中的线程进行唤醒。也就是说等待和唤醒必须是同一个锁。而锁可以是任意对象,所以被任意对象调用的方法定义在Object中。

class Res
{
String name;
String sex;
Boolean flag=false;
} class Input implements Runnable
{
private Res r;
Input(Res r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized(r)
{
if(r.flag)
{
try
{
r.wait();//如果flag=ture,说明资源中已经有了生产的对象,那么不再生产了,生产线程就wait
}
catch (Exception e)
{
e.printStackTrace();
}
}
if (x==0)
{
r.name = "Mike";
r.sex="man";
}
else
{
r.name = "丽丽";
r.sex="女";
}
r.flag = true;//改变flag标记
r.notify();//唤醒线程池中的第一个等待线程,只在本程序中就是out
}
x = (x+1)%2; }
}
} class Output implements Runnable
{
private Res r;
Output(Res r)
{
this.r = r;
}
public void run()
{
while(true)
{
synchronized(r)
{
if(!r.flag)
{
try
{
r.wait();//如果资源中没有生产对象,那么就没有可以打印的对象,这是输出就wait
}
catch (Exception e)
{
e.printStackTrace();
}
} System.out.println(r.name + "..." +r.sex);
r.flag = false;//改变标记
r.notify();//唤醒线程池中的第一个等待线程,本程序中即in
}
}
}
} class ThreadCommunication
{
public static void main(String[] args)
{
Res r = new Res();
Input in = new Input(r);
Output out = new Output(r); Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}

优化代码

class Res
{
private String name;
private String sex;
private Boolean flag=false; public synchronized void set(String name,String sex)
{
if (flag)
{
try
{
this.wait();
}
catch (Exception e)
{
e.printStackTrace();
}
this.name = name;
this.sex = sex;
flag = ture;
this.notify();
} }
public synchronized void out()
{
if (!flag)
{
try
{
this.wait();
}
catch (Exception e)
{
e.printStackTrace();
}
System.out.println(name + "..." + sex);
flag = false;
this.notify();
}
}
} class Input implements Runnable
{
private Res r;
Input(Res r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized(r)
{
if (x==0)
{
r.set("Mike","man");
}
else
{
r.set("丽丽","女");
}
}
x = (x+1)%2;
}
}
} class Output implements Runnable
{
private Res r;
Output(Res r)
{
this.r = r;
}
public void run()
{
while(true)
{
synchronized(r)
{
r.out();
}
}
}
} class ThreadCommunication
{
public static void main(String[] args)
{
Res r = new Res();
Input in = new Input(r);
Output out = new Output(r); Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}

当多个线程操作同一个资源,且同一个操作也有多个线程时,就需要使用while判断标记,并用notifyAll唤醒所有线程。

class FactoryDemo
{
public static void main(String[] args)
{
Resource r = new Resource();
Product pro = new Product(r);
Consumer con = new Consumer(r);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
} class Product implements Runnable
{
private Resource r = new Resource();
Product(Resource r)
{
this.r = r;
}
public void run()
{
while (true)
{
r.set("商品");
}
}
} class Consumer implements Runnable
{
private Resource r = new Resource();
Consumer(Resource r)
{
this.r = r;
}
public void run()
{
while (true)
{
r.out();
}
}
} class Resource
{
private String name;
private int count = 1;
private boolean flag = false;
public synchronized void set(String name)
{
while (flag)//使用while判断标记,避免线程在判断标记之后醒了不判断标记
{
try
{
this.wait();
}
catch (Exception e)
{
}
}
this.name = name + "--" + count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
this.notifyAll();
}
public synchronized void out()
{
while (!flag)//使用while判断标记,避免线程在判断标记之后醒了不从新判断标记
{
try
{
wait();
}
catch (Exception e)
{
}
}
System.out.println(Thread.currentThread().getName()+"...消费者.................."+this.name);
flag = false;
this.notifyAll();
}
}

但notifyAll唤醒对方线程的同时也把本方的线程唤醒了,这是我们不希望看到的。对于该问题的优化,参见Lock接口

Java:多线程<三>死锁、线程间通讯的更多相关文章

  1. (Java多线程系列三)线程间通讯

    Java多线程间通讯 多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同. 1.使用wait()和notify()方法在线程中通讯 需求:第一个线程写入(input)用户,另一个线程 ...

  2. java多线程同步以及线程间通信详解&消费者生产者模式&死锁&Thread.join()(多线程编程之二)

    本篇我们将讨论以下知识点: 1.线程同步问题的产生 什么是线程同步问题,我们先来看一段卖票系统的代码,然后再分析这个问题: package com.zejian.test; /** * @author ...

  3. Java多线程编程(6)--线程间通信(下)

      因为本文的内容大部分是以生产者/消费者模式来进行讲解和举例的,所以在开始学习本文介绍的几种线程间的通信方式之前,我们先来熟悉一下生产者/消费者模式.   在实际的软件开发过程中,经常会碰到如下场景 ...

  4. Java多线程编程核心技术---线程间通信(一)

    线程是操作系统中独立的个体,但这些个体如果不经过特殊处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一.线程间通信可以使系统之间的交互性更强大,在大大提高CPU利用率的同时还会使程序员对各 ...

  5. java多线程三之线程协作与通信实例

    多线程的难点主要就是多线程通信协作这一块了,前面笔记二中提到了常见的同步方法,这里主要是进行实例学习了,今天总结了一下3个实例: 1.银行存款与提款多线程实现,使用Lock锁和条件Condition. ...

  6. Java多线程编程(5)--线程间通信

    一.等待与通知   某些情况下,程序要执行的操作需要满足一定的条件(下文统一将其称之为保护条件)才能执行.在单线程编程中,我们可以使用轮询的方式来实现,即频繁地判断是否满足保护条件,若不满足则继续判断 ...

  7. Java多线程编程核心技术---线程间通信(二)

    通过管道进行线程间通信:字节流 Java提供了各种各样的输入/输出流Stream可以很方便地对数据进行操作,其中管道流(pipeStream)是一种特殊的流,用于在不同线程间直接传送数据,一个线程发送 ...

  8. java多线程5:线程间的通信

    在多线程系统中,彼此之间的通信协作非常重要,下面来聊聊线程间通信的几种方式. wait/notify 想像一个场景,A.B两个线程操作一个共享List对象,A对List进行add操作,B线程等待Lis ...

  9. java 多线程6(线程的·通讯)

    问题1: 为什么wait() 和 notify()是Object类中的方法,而不是Thread类中的方法呢? 答:因为锁是任意对象的所以要在Object类中,如果在Thread类中锁对象不是任意的了. ...

  10. C++多线程编程(三)线程间通信

    多线程编程之三——线程间通讯 作者:韩耀旭 原文地址:http://www.vckbase.com/document/viewdoc/?id=1707 七.线程间通讯 一般而言,应用程序中的一个次要线 ...

随机推荐

  1. Android 去除最上面应用名称及图标

    @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); r ...

  2. 将HTML5 Canvas的内容保存为图片借助toDataURL实现

    将HTML5 Canvas的内容保存为图片主要思想是借助Canvas自己的API - toDataURL()来实现,具体实现如下,感兴趣的朋友可以参考下哈,希望对你有所帮助 <html> ...

  3. s3c2440 移值u-boot-2016.03 第4篇 支持NAND flash 识别

    1, /include/configs/smdk2440.h 中添加 #define CONFIG_CMD_NAND 编译 drivers/mtd/nand/built-in.o: In functi ...

  4. python-操作excel数据文件

    1.excel文件操作 读文件xlrd模块:

  5. JS变量、内存、作用域小结

    确保占用最少的内存可以让页面获得更好的性能,优化内存占用的最佳方式:为执行中的代码 只保存必要的数据.一旦数据不再有用,最好通过将其值置为null来释放其引用.适用于大多 数全局变量和全局对象的属性. ...

  6. Linux C Programing - Arguments(2)

    #include <iostream> #include <stdlib.h> #include <stdio.h> //printf #include <u ...

  7. Team Queue (uva540 队列模拟)

    Team Queue Queues and Priority Queues are data structures which are known to most computer scientist ...

  8. JAVA基础知识之JDBC——RowSet

    RowSet概念 在C#中,提供了一个DataSet,可以把数据库的数据放在内存中进行离线操作(读写),操作完成之后再同步到数据库中去,Java中则提供了类似的功能RowSet. RowSet接口继承 ...

  9. android小知识之fragment中调用startActivityForResult(Intent intent,int requestcode)所遇到的问题

    大家都知道对于Activity和Fragment都可以注册OnActivityResult()方法,但是要注意几点: a.当activity和fragment都注册了OnActivityResult( ...

  10. 浅谈用ModelSim+Synplify+Quartus来实现Altera FPGA的仿真

    浅谈用ModelSim+Synplify+Quartus来实现Altera FPGA的仿真 工作内容: Mentor公司的ModelSim是业界最优秀的HDL语言仿真软件,它能提供友好的仿真环境,是业 ...