并发编程笔记二:synchronized锁住了谁?

点点圈 提交于 2019-12-01 04:44:45

在并发编程中要使用到关键字synchronized,当我们用synchronized关键字修饰一个方法时,代表着一个锁(Lock),那么这个锁的对象是什么,也就是它锁住了谁?

synchronized的使用情况大概就是下面几种:

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

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

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

看下面代码:

public class MultiThread {

	private static int num = 0;
	
	/** static */
	public  synchronized void printNum(String tag){
		try {
			
			if(tag.equals("a")){
				num = 100;
				System.out.println("tag a, set num over!");
				Thread.sleep(1000);
			} else {
				num = 200;
				System.out.println("tag b, set num over!");
			}
			
			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();
		
	}
}

printNum方法加了synchronized 关键字,根据输入参数不同打印不同信息,当我们执行main方法时,发现貌似synchronized没起作用。控制台输入如下:

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

这是因为synchronized 锁住的是对象,线程t1t2分别获取的是m1,m2的锁,他们并没有在获取锁上有竞争关系,因此,出现非同步的结果。

那如果要让printNum方法在多个对象之间也是线程安全的呢,一个对象在执行这个方法时,其他对象必须阻塞等待,一次只能有一个对象能执行这个方法。只需要加个static关键字来修饰printNum方法,这时synchronized 关键字锁住的就是MultiThread 的.class类了。

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

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

tag b, set num over!
tag b, num = 200
tag a, set num over!
tag a, num = 100
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!