`

java并发 wait,notify,notifyAll,synchronized(一)

 
阅读更多

       首先,调用一个Object的wait与notify/notifyAll的时候,必须保证调用代码对该Object是同步的,也就是说必须在作用等同于synchronized(obj){......}的内部才能够去调用obj的wait与notify/notifyAll三个方法,否则就会报错:

  java.lang.IllegalMonitorStateException:current thread not owner

 

方法的详细解释:

  wait():

  等待对象的同步锁,需要获得该对象的同步锁才可以调用这个方法,否则编译可以通过,但运行时会收到一个异常:IllegalMonitorStateException。

调用任意对象的 wait() 方法导致该线程阻塞,该线程不可继续执行,并且该对象上的锁被释放。

  notify():

  唤醒在等待该对象同步锁的线程(只唤醒一个,如果有多个在等待),注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。

调用任意对象的notify()方法则导致因调用该对象的 wait()方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。

  notifyAll():

  唤醒所有等待的线程,注意唤醒的是notify之前wait的线程,对于notify之后的wait线程是没有效果的。

 

    可以认为,每个对象实例都有一个wait set线程的休息室,当在该实例调用wait()方法的时候,就将当前线程放入该对象实例的wait set,并释放该对象上的锁。当在改对象上调用notify,或者notifyAll的时候,就是释放该对象wait set休息室里面的线程。

    由此,可以构建一系列的线程安全工具类

 

代码实例:

 

/**
 * 
 */
package com.mutex;

/**
 * 用wait(),notify()实现线程的互斥
 * 
 * 当MainTask运行10次以后,SubTask运行5次,如此依次循环交替执行
 * 
 */
public class MainClient {
	
	//决定线程是否运行
	public static volatile boolean notifyRun=true;
	
	//对象锁
	public static final Object Lock=new Object();
	

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception{
	
		//主任务运行
		new Thread(new MainTask()).start();
		
		Thread.sleep(1000);
		
		//子任务运行
		new Thread(new SubTask()).start();
		

	}

}

 

 

     

package com.mutex;

public class MainTask implements Runnable {

	private int n = 10;


	@Override
	public void run() {

		while (true) {
			
			System.out.println(" -------- MainTask -----------");
			
			//获取对象MainClient.Lock上的锁
			synchronized (MainClient.Lock) {
				
				if(!MainClient.notifyRun){
					//唤醒MainClient.Lock wait set中的所有线程
					MainClient.Lock.notifyAll();
					MainClient.notifyRun=true;
				}
				
				if(MainClient.notifyRun){
					
					for (int i = 1; i <= n; i++) {
						System.out.println("MainTask run." + i);
					}
					
					try {
						//本线程放入wait set,释放对象MainClient.Lock上的锁
						MainClient.Lock.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
			}

		}

	}
}

 

 

 

    

package com.mutex;

public class SubTask implements Runnable{
	
	private int n=5;
	

	@Override
	public void run() {
		
		while(true){
			
			System.out.println(" -------- SubTask -----------");
			
			//获取对象MainClient.Lock上的锁
			synchronized (MainClient.Lock) {
				
				if(!MainClient.notifyRun){
					try {
						MainClient.Lock.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					MainClient.notifyRun=true;
				}
				
				for(int i=1;i<=n;i++){
					System.out.println("SubTask run."+i);
				}
				
				
			    //本线程放入wait set,释放对象MainClient.Lock上的锁,让MainTask运行
			    MainClient.Lock.notifyAll();
			    MainClient.notifyRun=false;
			}
			
			
		}
		
		
	}

}

 

 

运行结果:

 -------- MainTask -----------

MainTask run.1

MainTask run.2

MainTask run.3

MainTask run.4

MainTask run.5

MainTask run.6

MainTask run.7

MainTask run.8

MainTask run.9

MainTask run.10

SubTask run.1

SubTask run.2

SubTask run.3

SubTask run.4

SubTask run.5

 -------- SubTask -----------

 -------- MainTask -----------

MainTask run.1

MainTask run.2

MainTask run.3

MainTask run.4

MainTask run.5

MainTask run.6

MainTask run.7

MainTask run.8

MainTask run.9

MainTask run.10

SubTask run.1

SubTask run.2

SubTask run.3

SubTask run.4

SubTask run.5

 -------- SubTask -----------

 -------- MainTask -----------

MainTask run.1

MainTask run.2

MainTask run.3

MainTask run.4

MainTask run.5

MainTask run.6

MainTask run.7

MainTask run.8

MainTask run.9

MainTask run.10

SubTask run.1

SubTask run.2

SubTask run.3

SubTask run.4

SubTask run.5

 -------- SubTask -----------

 -------- MainTask -----------

MainTask run.1

MainTask run.2

MainTask run.3

MainTask run.4

MainTask run.5

MainTask run.6

MainTask run.7

MainTask run.8

MainTask run.9

MainTask run.10

SubTask run.1

SubTask run.2

SubTask run.3

SubTask run.4

SubTask run.5

 -------- SubTask -----------

 -------- MainTask -----------

MainTask run.1

MainTask run.2

MainTask run.3

MainTask run.4

MainTask run.5

MainTask run.6

MainTask run.7

MainTask run.8

MainTask run.9

MainTask run.10

SubTask run.1

SubTask run.2

SubTask run.3

SubTask run.4

SubTask run.5

   

 

分享到:
评论

相关推荐

    Java 同步锁 wait notify 学习心得

    标题和描述概述的知识点主要集中在Java的多线程机制中,特别是`wait`和`notify`方法在同步锁中的应用。这些方法对于控制线程之间的交互至关重要,尤其是在资源有限或需要确保数据一致性的情况下。 ### Java同步锁...

    Java 中Object的wait() notify() notifyAll()方法使用

    在Java并发编程中,Object的wait()、notify()和notifyAll()方法是非常重要的概念,这三个方法都是Object类的方法,可以认为任意一个Object都是一种资源(或者资源的一个代表)。在并发编程中,线程安全是非常重要的...

    java并发编程实战源码,java并发编程实战pdf,Java

    3. **并发控制**:Java提供了多种并发控制工具,包括synchronized、wait()、notify()、notifyAll()、ReentrantLock(可重入锁)、Semaphore(信号量)和CountDownLatch(倒计时器)等。这些工具用于协调不同线程的...

    wait_notify_demo

    `wait()`、`notify()`和`notifyAll()`是Java中的三个关键字,它们属于Object类的方法,主要用于线程间的通信,尤其在实现生产者消费者模式时发挥着重要作用。本文将深入探讨这些方法以及如何在实际场景中应用它们。 ...

    Java多线程wait和notify

    总结来说,Java的 `wait()` 和 `notify()` 提供了一种在多线程环境中控制线程执行的机制。通过合理使用这些方法,我们可以实现线程间的协作,精确控制子线程的运行状态。然而,这种方式虽然灵活,但管理起来相对复杂...

    Java的sychronized、wait和notify范例

    `synchronized`关键字、`wait()`和`notify()`方法是Java多线程中用于控制并发访问共享资源的重要工具,它们是Java内存模型(JMM)的一部分,主要用于解决线程间的同步问题。 一、`synchronized`关键字 `...

    java并发编程艺术

    在Java中,同步是控制多个线程访问共享资源的方式,主要通过`synchronized`关键字和`wait()`, `notify()`, `notifyAll()`方法实现。书中的内容可能会涵盖如何使用这些机制来确保数据的一致性和完整性。 锁机制是...

    Java的wait(), notify()和notifyAll()使用心得

    Java中的`wait()`, `notify()`, 和 `notifyAll()` 是多线程编程中的关键工具,它们用于在并发环境中协调线程间的交互。这些方法都定义在`java.lang.Object`类中,因为它们与对象的监视器(monitor)概念密切相关。...

    (PDF带目录)《Java 并发编程实战》,java并发实战,并发

    2. **同步机制**:Java中的同步机制包括`synchronized`关键字、`wait()`, `notify()`和`notifyAll()`方法,以及`Lock`接口和相关的实现,如`ReentrantLock`。这些机制用于控制对共享资源的访问,防止数据不一致和竞...

    wait和notifyAll方法的使用示例

    当其他线程调用同一个对象的 `notify()` 或 `notifyAll()` 方法时,等待线程有机会重新获得锁并继续执行。需要注意的是,调用 `wait()` 方法必须在 `synchronized` 块或方法中进行,否则会抛出 `...

    java并发编程书籍

    此外,还有`wait()`, `notify()`, `notifyAll()`方法,它们与`synchronized`结合使用,实现线程间的通信。 3. ** volatile 关键字**:`volatile`用于保证共享变量的可见性,防止指令重排序导致的问题。当多个线程...

    Java 并发编程实战.pdf

    Java中线程的通信通常依赖于Object类中的wait()、notify()和notifyAll()方法。这些方法可以让线程在等待某个条件成立时处于等待状态,当其他线程使得条件成立并调用notify()或notifyAll()方法时,等待的线程将被唤醒...

    Java多线程同步(wait()notify()notifyAll())[文].pdf

    本文将深入探讨Java中的wait()、notify()和notifyAll()方法,以及synchronized关键字和原子操作在多线程环境中的应用。 1. **wait()方法**: - wait()是Object类的一个方法,它的作用是让当前线程暂停执行并释放它...

    java并发实战中文文档

    此外,还会讨论线程的状态(新建、就绪、运行、阻塞和终止)以及线程间的通信,如使用`join()`方法和`wait()`, `notify()`, `notifyAll()`方法。 2. **同步机制**:Java中的`synchronized`关键字是实现线程同步的...

    java并发书籍xxxxxxx

    线程调用wait()会释放锁并进入等待状态,直到其他线程调用notify()或notifyAll()唤醒。 6. **ThreadLocal**:每个线程都有自己的ThreadLocal变量副本,提供线程局部存储,避免了线程安全问题。 7. **并发集合**:...

    详解Java程序并发的Wait-Notify机制

    Java程序并发的Wait-Notify机制是Java多线程编程中的一种重要同步工具,它允许线程之间通过共享对象进行通信和协作。这个机制基于Java的内置锁(也称为监视器锁),通常与`synchronized`关键字一起使用。在Java中,`...

    一个理解wait()与notify()的例子

    本文旨在解析一个具体的Java多线程示例代码,以帮助读者更好地理解`wait()`与`notify()`方法的作用及其实现机制。这两个方法是Java中实现线程间通信的重要手段之一,尤其在解决生产者消费者模型、读者写者问题等经典...

    深入理解Java并发之synchronized实现原理.docx

    Java并发编程中的synchronized关键字是实现线程安全的重要工具,它提供了一种互斥访问机制,确保了共享数据在同一时刻只能被一个线程访问。synchronized关键字有三种主要的应用方式: 1. 修饰实例方法:当...

    Java并发编程:设计原则与模式(第二版)

    读者将通过使用java.lang.thread类、synchronized和volatile关键字,以及wait、notify和notifyall方法,学习如何初始化、控制和协调并发操作。此外,本书还提供了有关并发编程的全方位的详细内容,例如限制和同步、...

Global site tag (gtag.js) - Google Analytics