`
leidiqiu
  • 浏览: 133001 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java 关于线程同步的问题

    博客分类:
  • JAVA
阅读更多

      Java 线程同步问题也不是什么新鲜问题了,这里做一个总结吧。

 

 

      线程同步时,调用一个 synchronized 的方法,所有的 synchronized 的方法都被锁定,其他的方法不受影响。

 

看一个例子:

 

package com.ldq;

public class Test06 {

	private static Obj o1;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		o1 = new Obj();

		new Thread() {
			public void run() {
				o1.method01();
			}
		}.start();

		new Thread() {
			public void run() {
				o1.method02();
			}
		}.start();

		new Thread() {
			public void run() {
				o1.method03();
			}
		}.start();

	}
}

class Obj {

	synchronized void method01() {
		while (true) {
			System.out.println("method01");
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	void method02() {
		while (true) {
			System.out.println("method02");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	synchronized void method03() {
		while (true) {
			System.out.println("method03");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

 

 

以上代码输出结果为:

method01
method02
method02
method02
method02
method02
method01
method02
method02
method02

 

      分析:首先生成一个对象 o1 ,它有 3 个方法,其中 method01 和 method03 有关键字 synchronized 修饰,说明这两个方法要做线程同步,而 method02 没有关键字 synchronized 修饰,说明不用做同步。可见,对象加锁操作是针对有 synchronized 关键字而言的。调用 synchronized 的方法,整个对象的所有 synchronized 的方法都被加锁,但是其他的方法不受影响。

 

 

      sleep() 和 wait() 的区别

 

      sleep() 是 Thread 类的方法,wait() 是 Object 类的方法,由于所有类都是 Object 的子类,因此所有类都有 wait() 方法,从源代码看 public final native void wait() ,wait() 方法是 final ,不允许重载或是覆盖的,并且是 native ,是由本机接口实现的,与 JVM 的相关。

 

      sleep() 就是让线程空转,但是仍然占用资源。wait() 用在 synchronized 修饰的方法里,让线程暂停,并释放资源,直到有别的线程调用 notify() 或者 notifyAll() 方法唤醒。

 

      对某一个对象,wait() 让线程进入等待池,notify() 唤醒一个线程,notifyAll() 唤醒所有的线程。

 

看代码吧:

 

 

package com.ldq;

public class Test07 {

	private static MyObj o1;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		o1 = new MyObj();

		new Thread() {
			public void run() {
				o1.method01();
			}
		}.start();

		new Thread() {
			public void run() {
				o1.method02();
			}
		}.start();

	}
}

class MyObj {

	synchronized void method01() {
		while (true) {

			System.out.println("method01");

			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			notify();

			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	synchronized void method02() {
		while (true) {

			System.out.println("method02");

			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			notify();

			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

 

 

 

输出为:

method01
method02
method01
method02
method01
method02

...

 

 

      分析:匿名线程1执行完method01后,notify() 等待的线程,wait() 释放锁,匿名线程2获得锁后输出,notify() 等待的匿名线程1,自己 wait() 释放锁,此时,匿名线程1就可以继续执行,如此循环 ...

 

 

分享到:
评论
6 楼 scholers 2011-01-15  
1、synchronized关键字的作用域有二种:
1)是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;
2)是某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。

2、除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。用法是: synchronized(this){/*区块*/},它的作用域是当前对象;

3、synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法;
5 楼 lx_corn 2011-01-14  
线程同步时,调用一个 synchronized 的方法,所有的 synchronized 的方法都被锁定,其他的方法不受影响。
  果然 问题都是这句引起的。。
4 楼 zhangyou1010 2011-01-14  
“ 线程同步时,调用一个 synchronized 的方法,所有的 synchronized 的方法都被锁定,其他的方法不受影响。”

要看你怎么用synchronized吧?
3 楼 buptwhisper 2011-01-14  
楼主是不是有点错误?
"线程同步时,调用一个 synchronized 的方法,所有的 synchronized 的方法都被锁定,其他的方法不受影响。"我认为是不正确的。
synchronized 锁的是当前对象实例,跟其它的synchronized 方法是没有任何冲突与联系的。楼主的例子中之所以出现这样的情况,是因为你用的是同一个实例罢了。当你在调用某个synchronized 时,首先去取得对应对象的锁,如果没有被使用,则执行该方法;而如果已经被使用,则等待;特别地,如果你synchronized 的是static方法,锁的是对应的Class对象。
2 楼 神之小丑 2011-01-14  
单实例多线程notify 和notifyAll唤醒的是此实例上的等待的线程
1 楼 yousteely 2011-01-13  
分享成果是一种美德

相关推荐

Global site tag (gtag.js) - Google Analytics