在多个线程要互斥访问数据,
但线程间需要同步时——例如任务分多个阶段,特定线程负责特定阶段的情况,
经常合作使用synchronized 和 wait()

/**
*
* 计算输出其他线程锁计算的数据
* @author
*
*/
public class Main {
public static void main(String[] args) {
ThreadB b = new ThreadB();
b.start();// 启动计算线程
synchronized (b) {
try {
System.out.println("等待对象b完成计算...");// 当前线程A等待
b.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("b对象计算的总和是:" + b.total);
}
}
}
public class ThreadB extends Thread {
int total; public void run() {
synchronized (this) {
for (int i = 0; i < 101; i++) {
total += i;
}
//计算操作结束
notify();//唤醒在此对象监视器上等待的单个线程,在本例中线程A被唤醒
}
}
}

synchronized(b)导致了b上开启了同步锁。也就是说
只要存在 synchronized (b) 就会等待解锁。
也就是说A里的synchronized(b) {} 就是为了防止在执行的时候B里的synchronized(this){ } 代码段同时执行。

来个时间线。
1. A: synchronized (b) {
(这时候拿到b的锁,其他同步段不能执行,在等待中)
2.      try {
          System.out.println("等待对象b完成计算。。。");
          b.wait();
          (这时候A放弃b锁,让B执行)
3. B: synchronized (this) {
            for (int i = 0; i < 101; i++) {
                total += i;
            }
            notify();
            (唤醒A)
4. A:继续执行。

还可以用于方法前标示同步方法
比如:
public synchronized void methodA(){}
wait()是Object的方法,意味着所有的对象都有这个方法。
调用这个方法时表示执行这个方法的当前线程放弃执行,进入等待状态,同时放弃对象锁,其它线程就可以进入由同一个对象锁控制的同步块或同步方法。

wait()时会先释放当前线程所拥有的锁,
当从wait状态返回时,会再次获取之前的锁,之后再执行后续代码。
这点由JVM保证,可查JDK文档。

为什么wait()一定要在同步方法或同步块中调用?
这是因为wait()命令的发出者必须首先拥有锁,或者说只有手中持有锁的线程才有资格等待以交出控制权。wait()/notify()这种机制的引入本身就是为了在资源独占(表现为synchronized)的前提下合作,所以只有配合锁使用才有意义。

wait()/notify()是相互协作的,刚开始怎么想也想不明白要独占资源
现在想了一下,好像有点眉目了:
一个线程计算结果,另外一个线程等待结果,但是两个线程都要访问某个共同变量,一个线程往里放结果,另外一个线程从中取结果。上面例子的total就是共同变量。因为要访问共同变量,所以涉及到资源独占的问题,所以要加上synchronized关键字。

wait()促使当前线程放弃锁,其他等待线程可以拿到锁了
sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

http://bbs.csdn.net/topics/330005504

java synchronized wait的更多相关文章

  1. Java Synchronized Blocks

    From http://tutorials.jenkov.com/java-concurrency/synchronized.html By Jakob Jenkov   A Java synchro ...

  2. java synchronized(一)

    java synchronized主要用于控制线程同步,中间有很多小的细节,知识,这里我简单的整理一下,做个记录.主要用于方法和代码块的控制 先说说方法控制 模拟银行存款和取款,创建一个Account ...

  3. java synchronized使用

    java synchronized 基本上,所有并发的模式在解决线程冲突问题的时候,都是采用序列化共享资源的方案.这意味着在给定时刻只允许一个任务访问该资源.这个一般通过在代码上加一条锁语句实现,因为 ...

  4. Java synchronized 详解

    Java synchronized 详解 Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 1.当两个并发线程访问同一个对象object ...

  5. Java Synchronized 关键字

    本文内容 Synchronized 关键字 示例 Synchronized 方法 内部锁(Intrinsic Locks)和 Synchronization 参考资料 下载 Demo Synchron ...

  6. Java synchronized 关键字详解

    Java synchronized 关键字详解 前置技能点 进程和线程的概念 线程创建方式 线程的状态状态转换 线程安全的概念 synchronized 关键字的几种用法 修饰非静态成员方法 sync ...

  7. Java synchronized对象级别与类级别的同步锁

    Java synchronized 关键字 可以将一个代码块或一个方法标记为同步代码块.同步代码块是指同一时间只能有一个线程执行的代码,并且执行该代码的线程持有同步锁.synchronized关键字可 ...

  8. java synchronized详解

    Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchronized(this ...

  9. Java synchronized

    1. 将synchronized加在方法上, 即可实现对此方法的同步 public synchronized void deposit(float amt) { float tmp = amount; ...

  10. Java synchronized指南

    在多线程程序中,同步修饰符用来控制对临界区代码的访问.其中一种方式是用synchronized关键字来保证代码的线程安全性.在Java中,synchronized修饰的代码块或方法不会被多个线程并发访 ...

随机推荐

  1. GSM嗅探

    GSM初探 大家应该都听说过HTTP协议,又听说WEB服务,每一个服务的背后都有一个协议在工作着.所谓的没有规矩不成方圆,说的就是这个道理,每一个细小的部分,都已经规定好,只要按照协议执行,就不会出现 ...

  2. jQuery Easyui DataGrid应用

    冻结列 $('#tbList').datagrid({ pagination: true, frozenColumns: [[ { field: 'BId',checkbox:'true',width ...

  3. IE6下window.location.href不跳转到相应url

    前天一同事遇到个看似很诡异的问题,就是<a href="javascript:void(0);" onclick="window.location.href=url ...

  4. JavaScript正则实战

    *:first-child { margin-top: 0 !important; } .markdown-body>*:last-child { margin-bottom: 0 !impor ...

  5. C#基础(八)——C#数据类型的转换

    C#数据类型的转换主要有以下几种方式: 1.强制转换 注意:char类型不能强制转换成int,如果使用强制转化,得到的是原整数的ASCII码值. 2.class.parse(string类型的变量), ...

  6. C# 判断点是否在多边形内

    /// <summary>/// 判断点是否在多边形内/// </summary>/// <param name="pnt">点</par ...

  7. Python urllib2多进程共享cookies

    如果想多个进程共享同一个cookies,不用每个进程都重新登录,可以就cookies保存到一个文件,然后多个进程直接共享一个锁来实现 1.一个进程登录完成后,把cookies保存到一个文件里面 sel ...

  8. MYSQL外键约束的参照操作

    如果表A的主关键字是表B中的字段,则该字段称为表B的外键,表A称为主表,表B称为从表.外键是用来实现参照完整性的,不同的外键约束方式将可以使两张表紧密的结合起来,特别是修改或者删除的级联操作将使得日常 ...

  9. drop column与set unused

    8i以前,如果需要删除表中的列,需要删除表然后重新建.现在,但我们需要删除一个列时,可以有以下两种方法: Logical Delete Physical Delete Logical Delete(逻 ...

  10. JS 实现取整(二)

    1.直接丢弃小数部分,保留整数部分 a:parseInt(1.5555) b: 0|1.5555 2.向上取整 a: Math.ceil(1.5555) b: (1.5555+0.5).toFixed ...