java synchronize初探

java锁机制初探,实例学习

 

 

package com.yjf.image;

public class TT implements Runnable {
	
	int a = 0;
	
	@Override
	public void run() {
		try {
			m1();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public synchronized void m1() throws InterruptedException {
		a = 1000;
		Thread.sleep(5000);
		System.out.println("m1:" + a);
	}
	
	public synchronized void m2() throws InterruptedException {
		Thread.sleep(1000);
		a = 2000;
		System.out.println("m2:" + a);
	}		

	public static void main(String[] args) throws InterruptedException {
		TT tt = new TT();
		Thread t = new Thread(tt);
		t.start();
		Thread.sleep(20);
		tt.m2();
		Thread.sleep(6000);
		System.out.println("main:" + tt.a);
	}
}

 

 

定义了一个线程类TT,实现Runnable接口,两个方法m1和m2都加了锁,main方法有两个线程:线程main和线程t。运行结果为:

m1:1000

m2:2000

main:2000

 

因为m1和m2都加了锁,代码先执行了t.start,即执行到了m1代码块,此时线程睡了5秒,但它睡着的时候还抱着当前对象的锁。在它睡着的过程中,代码执行到tt.m2();,但由于m2是个synchronised的方法,它要执行的话,必须要先获得一把锁,但这把锁被m1抱着,所以必须等到m1执行完成后,m2才能执行。

 

如果把m2的synchronized修饰符去掉,那么运行结果为:

m2:2000

m1:2000

main:2000

因为m1睡着了,抱着当前对象的锁,但m2不是一个synchronized方法,它执行前不用获得锁,所以在m1睡着的过程中,m2先执行完了。

 

如果把m1声明为public static synchronized void m1(),把m2声明为synchronized,把成员变量a变成static,运行结果为:

m2:2000

m1:2000

main:2000

分析:因为m1是static方法,它睡着的时候抱着一把锁,但这把锁不是当前对象的锁,而是当前类的锁。m2执行时,需要获得一把当前对象的锁,它当然可以获得。所以m2比m1先执行完。

 

如果把m2声明为public static synchronized void m2(),把m1声明为public static synchronized void m1(),把tt.m2()改为TT.m2(),执行结果为:

m1:1000

m2:2000

 

main:2000

 

分析:m1睡着的时候锁住了当前类,而m2执行的时候需要获得当前类的锁,所以必须等m1执行完把锁释放后,m2才能执行。

 

最后提一点,main方法中有这几句话:

                 t.start();

Thread.sleep(20);

 

TT.m2();

如果去掉中间这句:Thread.sleep(20);,会出现不一样的结果。因为主线程的优先级大于分支线程,CPU会这样分配时间。t.start(),启动一个线程,实际上不是启动,而是初始化了一个线程t,CPU会先分配时间片给TT.m2(),所以我加个Thread.sleep(20),让主线程睡一会,排除干扰。

 

你可能感兴趣的:(java)