synchronized锁住了谁

先来看一段代码

public class MultiThread {

	private static int num = 0;
	
	/** static */
	public  synchronized void printNum(String tag){
		try {
			
			if(tag.equals("a")){
				num = 200;
				System.out.println("tag a, set num over!");
				Thread.sleep(300);
			} else {
				num = 500;
				System.out.println("tag b, set num over!");
				//Thread.sleep(300);
			}
			
			System.out.println("tag " + tag + ", num = " + num);
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	//注意观察run方法输出顺序
	public static void main(String[] args) {
		
		//俩个不同的对象
		final MultiThread m1 = new MultiThread();
		final MultiThread m2 = new MultiThread();
		
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				m1.printNum("a");
			}
		});
		
		Thread t2 = new Thread(new Runnable() {
			@Override 
			public void run() {
				m2.printNum("b");
			}
		});		
		
		t1.start();
		t2.start();
		
	}
}

运行之后得到的结果由随机性:
可能是

tag b, set num over!
tag a, set num over!
tag b, num = 200
tag a, num = 200

也可能是

tag a, set num over!
tag b, set num over!
tag b, num = 500
tag a, num = 500

当然,还有其他的可能性,这里就不一一列举了。
可以看到,synchronized没起作用。这是因为synchronized锁住的是对象,线程t1,t2分别获取的是m1,m2的锁,他们并没有在获取锁上有竞争关系,因此,出现非同步的结果。
那如果要让printNum方法在多个对象之间也是线程安全的呢,一个对象在执行这个方法时,其他对象必须阻塞等待,一次只能有一个对象能执行这个方法。只需要加个static关键字来修饰printNum方法,这时synchronized关键字锁住的就是MultiThread的.class类了。
将printNum方法修改如下:

public static synchronized void printNum(String tag)
...

结果如下:

tag b, set num over!
tag b, num = 500
tag a, set num over!
tag a, num = 200

或者:

tag a, set num over!
tag a, num = 200
tag b, set num over!
tag b, num = 500

这时的输出结果就符合我们的预期了。

最后,总结一下:
synchronized的使用情况大概就是下面几种:

  • synchronized修饰非静态方法
  • synchronized修饰静态方法
  • 同步代码块的synchronized (this)
  • 同步代码块的synchronized (非this对象)
  • 同步代码块的synchronized (类.class)

synchronized修饰非静态方法、同步代码块的synchronized (this)用法和synchronized (非this对象)的用法锁的是对象,线程想要执行对应同步代码,需要获得对象锁。
synchronized修饰静态方法以及同步代码块的synchronized (类.class)用法锁的是类,线程想要执行对应同步代码,需要获得类锁。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值