您的位置:首页 > 编程语言 > Java开发

对java synchronized方法的深入理解

2015-05-03 22:38 851 查看
1. 首先加锁的是对象,而非代码。

package lei.com.Sychronized;

public class T2 extends Thread{
private String name;
public T2(String name)
{
	this.name=name;
}
private synchronized void test()
{
	while(true)
	{
		System.out.println(name+"执行中....");
	}
}
@Override
public void run() {
	this.test();
}
public static void main(String[] args) {
	T2 ta=new T2("ta");
	T2 tb=new T2("tb");
	ta.start();
	tb.start();
}

}


在上述代码中,虽然同步了test方法,但是由于创建了两个不同的对象,所以ta.start线程开始运行的时候只是对对象ta进行了加锁。同理tb.start时候,只是对对象tb进行了加锁。所以两个线程之间不会相互影响。两个线程的test方法能够同时执行。

package lei.com.Sychronized;

public class T4 extends Thread{
private String name;
private static int count=0;
public T4(String name)
{
	this.name=name;
}
public synchronized void test()
{
	
	
	this.count++;
	System.out.println("线程"+count+"开始执行....");
	try {
		this.sleep(100);
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
		System.out.println("线程"+count+"执行结束....");
	
}
@Override
public void run() {
	this.test();
}
public static void main(String[] args) {
	T4 ta=new T4("ta");
	for(int i=0;i<10;i++)
	{
	  (new T3(ta)).start();
	
	}

package lei.com.Sychronized;

public class T3 extends Thread {
	private T4 t4;
public T3(T4 t4)
{ 
	this.t4=t4;
}
@Override
public void run() {
 t4.test();
}

}				
}
}


上述代码中同步了test方法,但是在类T3中访问的都是同一个对象 ta的test方法,所以十个线程都是顺序执行的。
2. 其他线程可以在被加锁的线程执行时访问同一个对象没有被加锁的方法。
package lei.com.Sychronized;

public class T5 implements Runnable {
	private int a=0;
	private long startTime;
	public T5()
	{
		this.startTime=System.currentTimeMillis();
	}
	public synchronized  void updateA()
	{
		System.out.println("updateA方法开始执行...");
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("a的当前的值:"+a);
		a=800;
		System.out.println("updateA方法执行完毕...");

	}
		
		public  void  run() {
			this.updateA();
	}
	public  void updateB()
	{
		
	     a=600;
	     System.out.println("新线程updateB方法被执行...");
	}

		public static void main(String[] args) {
			T5 t5=new T5();
			
			new Thread(t5).start();
			try {
				Thread.sleep(20);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			t5.updateB();

		}

	}


输出结果:

updateA方法开始执行...
新线程updateB方法被执行...
a的当前的值:600
updateA方法执行完毕...
原因:首先方法updateA()被执行,此时对象t5被加锁,但是它的没有被加锁的方法updateB()仍然在updateA()执行的过程中可以执行。所以输出结果a的当前值为600而非0。
3. 由于加锁的是对象,所以当多个方法都加锁时,同一个时间段内,只能访问同一个对象的一个加锁方法.

package lei.com.Sychronized;

public class T implements Runnable {
private int a=0;
private long startTime;
public T()
{
	this.startTime=System.currentTimeMillis();
}
public synchronized  void updateA()
{
	a=1000;
	System.out.println("加锁方法被执行...");
	try {
		Thread.sleep(5000);
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	System.out.println("a的值:"+a);
	long currentTime=System.currentTimeMillis();
	System.out.println("方法upateA执行完成之后的时间为:"+(currentTime-this.startTime));

}
	
	public  void  run() {
		this.updateA();
}
public  synchronized void updateB()
{
	
	long currentTime=System.currentTimeMillis();
	System.out.println("方法upateB开始执行的时间为:"+(currentTime-this.startTime));

	try {
		Thread.sleep(1000);
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	
	System.out.println("updateB对象执行...");
	System.out.println("在updateB方法执行时,a的值:"+a);
	a=200;
}

	public static void main(String[] args) {
		T t=new T();
		
		new Thread(t).start();
		try {
			Thread.sleep(20);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		t.updateB();

	}

}


输出结果为:

加锁方法被执行...
a的值:1000
方法upateA执行完成之后的时间为:5000
方法upateB开始执行的时间为:5000
updateB对象执行...
在updateB方法执行时,a的值:1000
方法updateA()和方法updateB()都被加锁,由于调用两个方法的对象是同一个t.当updateA访问时t被加锁,updateB()不能执行。所以才出现上面结果。updateA()完全执行完毕后,释放对象锁t,updateB()才能执行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: