`

synchronized (this) 柳暗花明又一村

 
阅读更多

 今天写一个测试类,主要是测试wait(long timeout)到底会不会自动notify,到后来发现

一些很诡异的东西。

package com.hp.thread.chapter04;

public class WaitAndNotify {
	private Object obj = new Object();
	public static void testPureWait(){
		new Thread(new Runnable(){
			public void run() {
				synchronized (this) {
					try {
						System.out.println("thread 0");
						wait();
						System.out.println("thread 0 waited...");
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
		new Thread(new Runnable(){
			public void run() {
				synchronized (this) {
					try {
						System.out.println("thread 1");
						wait(1000);
						System.out.println("thread 1 waited...");
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
	}
	
	public void testWait1000(){
		new Thread(new Runnable(){
			public void run() {
				System.out.println("thread 0 " + this);
				synchronized (obj) {
					while(true){
						try {
							System.out.println("thread 0 running...");
							Thread.sleep(1000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			}
		}).start();
		new Thread(new Runnable(){
			public void run() {
				System.out.println("thread 1 " + this);
				synchronized (obj) {
					try {
						while(true){
							wait(1000);
							System.out.println("thread 1 waited...");
						}
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
	}
	//通过打印出来的this,发现2个是不同的结果,为什么呢?
	//因为this是指向当前对象的引用,不过方法中都是new Thread(new Runnable(){}).start()
	//方式来生成,都是通过匿名的方式,所以每次的this都是指向new Thread()的WaitAndNotify对象
	public void testWait1000_2(){
		new Thread(new Runnable(){
			public void run() {
				synchronized (this) {
					while(true){
						try {
							System.out.println("thread 0");
							System.out.println("thread 0 running...");
							Thread.sleep(1000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			}
		}).start();
		new Thread(new Runnable(){
			public void run() {
				synchronized (this) {
					try {
						while(true){
							System.out.println("thread 1");
							wait(1000);
							System.out.println("thread 1 waited...");
						}
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
	}
	
	public static void testWait(){
		new Thread(new Runnable(){
			public void run() {
				while(true){
					synchronized (this) {
						try {
							System.out.println("...");
							wait();
							System.out.println("waited...");
							notifyAll();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			}
		}).start();
		
		new Thread(new Runnable(){
			public void run() {
				while(true){
					synchronized (this) {
						try {
							notifyAll();
							System.out.println("notify...");
							wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			}
		}).start();
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
//		testPureWait();
//		testWait();
		new WaitAndNotify().testWait1000();
	}

}

 调用testWait1000_2方法得到的结果不是我期望(线程0始终在运行,线程1是不会运行的),但世界的结果恰恰相反,好事2个线程不相干,测试结果如下

thread 0
thread 0 running...
thread 1
thread 1 waited...
thread 0
thread 0 running...
thread 1
thread 0
thread 0 running...
thread 1 waited...
thread 1

 但是运行testWait1000正好是我要的结果,开始百思不得其解,后来打印this发现mystery了

thread 0 com.hp.thread.chapter04.WaitAndNotify$3@525483cd
thread 0 running...
thread 1 com.hp.thread.chapter04.WaitAndNotify$4@67f1fba0
thread 0 running...
thread 0 running...
thread 0 running...
thread 0 running...

 发现2个this的地址完全不一样,细想一下豁然开朗。

分享到:
评论
7 楼 tojaoomy 2013-05-20  
teasp 写道
tojaoomy 写道
teasp 写道
tojaoomy 写道
teasp 写道
匿名类的this当然是指向匿名类对象自身了。我好奇的是你为什么要“测试wait(long timeout)到底会不会自动notify”。测试的结果是什么呢?

结果是会notify

如果我告诉你你的结果是错误的呢?

错误的?不解,那就麻烦你说一下原因?
这是我的理解,timeout时间一过,该线程立马notify,不过会等待
对象锁,不是waiting状态了,而是等待锁的状态。

这是当然的啊,还用测试吗?我以为你测的是时间还没到,wait的线程就自己醒了呢。

呵呵,理论终归是理论,还是要实践的。
而我测试的目的是notify后的reaction是什么罢了。
6 楼 teasp 2013-05-20  
tojaoomy 写道
teasp 写道
tojaoomy 写道
teasp 写道
匿名类的this当然是指向匿名类对象自身了。我好奇的是你为什么要“测试wait(long timeout)到底会不会自动notify”。测试的结果是什么呢?

结果是会notify

如果我告诉你你的结果是错误的呢?

错误的?不解,那就麻烦你说一下原因?
这是我的理解,timeout时间一过,该线程立马notify,不过会等待
对象锁,不是waiting状态了,而是等待锁的状态。

这是当然的啊,还用测试吗?我以为你测的是时间还没到,wait的线程就自己醒了呢。
5 楼 tojaoomy 2013-05-20  
teasp 写道
tojaoomy 写道
teasp 写道
匿名类的this当然是指向匿名类对象自身了。我好奇的是你为什么要“测试wait(long timeout)到底会不会自动notify”。测试的结果是什么呢?

结果是会notify

如果我告诉你你的结果是错误的呢?

错误的?不解,那就麻烦你说一下原因?
这是我的理解,timeout时间一过,该线程立马notify,不过会等待
对象锁,不是waiting状态了,而是等待锁的状态。
4 楼 teasp 2013-05-20  
tojaoomy 写道
teasp 写道
匿名类的this当然是指向匿名类对象自身了。我好奇的是你为什么要“测试wait(long timeout)到底会不会自动notify”。测试的结果是什么呢?

结果是会notify

如果我告诉你你的结果是错误的呢?
3 楼 tojaoomy 2013-05-19  
package com.hp.thread;

import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CyclicBarrierTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		CyclicBarrier barrier = new CyclicBarrier(3,new Runnable() {
			
			@Override
			public void run() {
				System.out.println("get together");
			}
		});
		ExecutorService executor = Executors.newFixedThreadPool(3);
		executor.submit(new Thread(new Runner(barrier, "1号选手")));
        executor.submit(new Thread(new Runner(barrier, "2号选手")));
        executor.submit(new Thread(new Runner(barrier, "3号选手")));
        executor.shutdown();

	}

}

class Runner implements Runnable{
	private CyclicBarrier barrier;
	private String name;
	
	public Runner(CyclicBarrier barrier,String name) {
		this.barrier = barrier;
		this.name = name;
	}
	@Override
	public void run() {
		try {
			Thread.sleep(1000*(new Random().nextInt(2)));
			System.out.println( name + " ready...");
			barrier.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (BrokenBarrierException e) {
			e.printStackTrace();
		}
		System.out.println(name + "go!");
	}
	
}
2 楼 tojaoomy 2013-05-19  
teasp 写道
匿名类的this当然是指向匿名类对象自身了。我好奇的是你为什么要“测试wait(long timeout)到底会不会自动notify”。测试的结果是什么呢?

结果是会notify
1 楼 teasp 2013-05-17  
匿名类的this当然是指向匿名类对象自身了。我好奇的是你为什么要“测试wait(long timeout)到底会不会自动notify”。测试的结果是什么呢?

相关推荐

    java_synchronized详解

    - 如果一个线程正在访问对象的`synchronized(this)`同步代码块,其他线程仍然可以访问该对象的非`synchronized(this)`代码块。例如: ```java package ts; public class Thread2 { public void m4t1() { ...

    java中synchronized用法

    Synchronized 关键字的作用是取得对象的锁,而不是把一段代码或函数当作锁。每个对象只有一个锁与之相关联。实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。 当 ...

    synchronized的几种示例

    在Java编程语言中,`synchronized`关键字是一个重要的并发控制机制,用于确保多线程环境下的数据一致性。本文将深入探讨`synchronized`的几种使用示例,包括方法加锁、代码块加锁(针对`this`和对象)以及静态方法...

    java里面synchronized用法.doc

    Java 中的 synchronized 关键字是用于解决多线程并发问题的重要工具之一。它可以被用于方法、代码块和变量上,以实现对共享资源的互斥访问控制。本文将对 Java 中的 synchronized 用法进行详细的解释和分析。 一、...

    Android synchronized 测试案例

    当一个线程进入`synchronized`代码块或方法时,其他试图进入同一块的线程将被阻塞,直到持有锁的线程退出。 二、同步单个对象 1. 同步方法:在方法声明前加上`synchronized`关键字,使得每次只有一个线程能执行该...

    synchronized用法大全实例

    在Java多线程编程中,`synchronized`关键字是一个至关重要的工具,用于实现线程间的同步,以确保共享资源的安全访问。本实例大全将全面解析`synchronized`的使用方式,包括同步方法、同步语句块、类锁和对象锁。 ##...

    JAVA synchronized详解

    在Java编程语言中,`synchronized`是一个非常重要的关键字,它主要用于实现同步控制机制。通过使用`synchronized`,可以确保同一时刻只有一个线程能够访问被标记为同步的方法或代码块,从而避免多线程环境下的数据不...

    28.线程的同步机制-synchronized同步语句-synchronized(this)代码块是锁定当前对象.mp4

    在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。

    synchronized关键字的用法详解

    以下是一个具体的示例程序,用于演示多个线程访问同一个对象的`synchronized(this)`同步代码块时的行为。 ```java package threads; public class Thread1 implements Runnable { public void run() { ...

    volatile和synchronized的区别

    当一个线程访问某个对象的一个`synchronized`方法时,它就获得了该对象的锁,并且其他线程无法再访问该对象的其他`synchronized`方法。 - **互斥性**:通过`synchronized`关键字实现的锁具有互斥性,也就是说,一次...

    Synchronized关键字的用法

    synchronized (this) { count++; } } // 使用自定义锁 private final Object lock = new Object(); public void incrementWithCustomLock() { synchronized (lock) { count++; } } } ``` #### 性能...

    java锁机制Synchronizedjava锁机制Synchronized

    Java 锁机制 Synchronized 是 Java 语言中的一种同步机制,用于解决多线程并发访问共享资源时可能出现的一些问题。 Java 锁机制 Synchronized 的概念 在 Java 中,每个对象都可以被看作是一个大房子,其中有多个...

    Java synchronized使用案例

    Java中的`synchronized`关键字是多线程编程中的一个重要概念,用于控制并发访问共享资源,以保证数据的一致性和完整性。这个关键词提供了互斥锁机制,防止多个线程同时执行同一段代码,确保了线程安全。 一、`...

    synchronized并发讲解源码.zip

    在Java编程语言中,`synchronized`关键字是一个非常重要的并发控制机制,用于保证多线程环境下的数据一致性。本文将深入解析`synchronized`的工作原理、使用方式以及它在并发编程中的重要性。通过分析提供的源码,...

    synchronized详解

    通过使用`synchronized`,可以确保同一时间只有一个线程能够执行特定代码块,从而防止数据的不一致性和线程安全问题。下面将详细介绍`synchronized`的用法及其在不同场景下的应用。 1. 同步方法: 当`synchronized...

    synchronized关键字的实质及用法

    - **方法同步**:在方法声明前加上`synchronized`关键字,这将使得整个方法成为同步方法,每次只有一个线程可以执行该方法。 ```java public synchronized void someMethod() { // ... } ``` - **代码块...

    synchronized 的理解

    这意味着在任意时刻,都只有一个线程可以访问该实例的所有`synchronized`方法,或者进入由`synchronized(this)`标记的代码块。对于静态方法,锁对象则是该类的Class对象。 ```java public class MyClass { private...

    Java synchronized详细解读.docx

    `synchronized`提供了一种机制,使得在多线程环境中,对特定代码或方法的访问变得有序和安全。 首先,`synchronized`可以应用于两种情况:同步方法和同步代码块。同步方法是通过在方法声明前加上`synchronized`...

    java synchronized demo

    在Java编程语言中,`synchronized`关键字是一个非常重要的概念,它用于实现线程同步,以确保多线程环境下的数据一致性与安全性。本示例"java synchronized demo"旨在探讨`synchronized`关键字的用法及其作用机制。...

    java同步synchronized关键字用法示例

    Java中的`synchronized`关键字是多线程编程中的一个重要概念,用于控制并发访问共享资源时的同步机制。在Java中,当多个线程试图同时访问和修改同一块代码或数据时,可能会导致数据不一致的问题。为了解决这个问题,...

Global site tag (gtag.js) - Google Analytics