论坛首页 Java企业应用论坛

同一任务和对象锁的问题

浏览 13691 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (9) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-08-04   最后修改:2010-08-04
   偶尔翻开java编程思想看看多线程的篇章,意焦突然卡在某个问题上不动了。这个问题看过多少次多少遍了,此刻才领会,顿时感觉自己好笨拙的思维。

    问题是这样的:一般来说,在多线程程序中,某个任务在持有某对象的锁后才能运行任务,其他任务只有在该任务释放同一对象锁后才能拥有对象锁,然后执行任务。于是,想到,同一个任务在持有同一个对象的锁后,在不释放锁的情况下,继续调用同一个对象的其他同步(synchronized)方法,该任务是否会再次持有该对象锁呢?

    答案是肯定的。同一个任务在调用同一个对象上的其他synchronized方法,可以再次获得该对象锁。

    多线程编程是一件很微妙的事情,这里考验人的不是大局而是细节,细节的细节。希望能唤醒自己愚笨的思维。

 package thread.thread1;

/**
 * 同一任务可以再次持有对象锁 create on 2010.08.04 08:27
 * 
 * @since jdk1.6
 * @author maozj
 * @version 1.0
 * 
 */
public class SynchronizedClassHolder {
	/**
	 * Test client
	 * @param args
	 */
	public static void main(String[] args) {
		new Thread() {
			public void run() {
				new SynchronizedClassHolder().f1();
			}
		}.start();
	}

	private static int count = 10;

	/**
	 * synchronized f1()
	 */
	public synchronized void f1() {
		if (--count > 0) {
			System.out.println("f1() calling f2() count " + count);
			f2();
		}
	}

	/**
	 * synchronized f2()
	 */
	public synchronized void f2() {
		if (--count > 0) {
			System.out.println("f2() calling f1() count " + count);
			f1();
		}
	}
}

输出:
f1() calling f2() count 9
f2() calling f1() count 8
f1() calling f2() count 7
f2() calling f1() count 6
f1() calling f2() count 5
f2() calling f1() count 4
f1() calling f2() count 3
f2() calling f1() count 2
f1() calling f2() count 1
   发表时间:2010-08-04  
期待高手讲解原理
0 请登录后投票
   发表时间:2010-08-04  

我是这样理解的。 Java Monitors Are Reentrant 也就是当前线程如果已经有了一个Object a的锁,那么此线程想再次获取这个a的锁时,可以继续获取。然后在此线程对于该锁的计数上+1. 比如

 

synchronized  m1(){
//加入此时对锁a的计数是N
 m2();  //进入m2的方法体之后锁计数是N+1,离开m2后是N
}
synchronized m2(){}

 这样就能保证锁的正确获取和释放了。

 

 个人理解,仅供参考~

0 请登录后投票
   发表时间:2010-08-04  
嗯。深入java虚拟机中说:一个线程可以多次对同一个对象上锁。对于每一个对象,java虚拟机维护一个加锁计数器,线程每获得一次该对象,计数器就加1,每释放一次,计数器就减1,当计数器值为0时,锁就被完全释放了。
0 请登录后投票
   发表时间:2010-08-04  
maozj 写道
同一个任务在调用同一个对象上的其他synchronized方法,可以再次获得该对象锁。


是这样的吗?

我一直认为是,已经持有锁了,可以继续执行synchronized方法。
不是你说的“可以再次获得该对象锁”。
0 请登录后投票
   发表时间:2010-08-04  
hardPass 写道
maozj 写道
同一个任务在调用同一个对象上的其他synchronized方法,可以再次获得该对象锁。


是这样的吗?

我一直认为是,已经持有锁了,可以继续执行synchronized方法。
不是你说的“可以再次获得该对象锁”。


应该是采用的是引用计数的方法来实现的课重入。
0 请登录后投票
   发表时间:2010-08-04  
hardPass 写道
maozj 写道
同一个任务在调用同一个对象上的其他synchronized方法,可以再次获得该对象锁。


是这样的吗?

我一直认为是,已经持有锁了,可以继续执行synchronized方法。
不是你说的“可以再次获得该对象锁”。


-------------------
呵呵 你一直认为?
0 请登录后投票
   发表时间:2010-08-04   最后修改:2010-08-04
每个对象有一个监视器对象,一个线程获取到该监视器以后。其它线程就只能进入该对象监视器的等待队列中,等待线程处于等待运行状态,等获取监视器的线程释放锁以后,从等待队列中激活一线程进行运行。。。

如果两个不同的同步方法,没有共享相同状态信息,考虑使用不同的监视器对象,也就是所说的拆分锁
0 请登录后投票
   发表时间:2010-08-04  
把f1() f2()看作是2个对象,是不是更好解释一些?
0 请登录后投票
   发表时间:2010-08-04  
简单来说,对象锁是可重入的,可重入针对的是每线程。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics