面试——多线程访问同步方法的7种情况

4 篇文章 0 订阅
1 篇文章 0 订阅

前言:多线程是Java高级部分而同步是多线程的重点,面试的常考题。今天我总结了7种常考题。

1、当两个线程同时访问同一个对象的同步方法:

这种情况上次有类似的例子(对象锁的方法锁):https://mp.csdn.net/postedit/85791038

	static SynchronizedObectMethod3 intance=new SynchronizedObectMethod3();
	public static void main(String[] args) {
		Thread th1=new Thread(intance);
		Thread th2=new Thread(intance);
		th1.start();
		th2.start();
		while(th1.isAlive() || th2.isAlive()){
			
		}
		System.out.println("finished");
	}
	public void run() {
		method();
	}
	public  synchronized void method(){
		System.out.println("我是对象锁的方法修饰符形式,我叫:"+Thread.currentThread().getName());
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"结束");
	}

执行结果:先是第一条执行,执行完后再执行第二条。因为它们的是同一个实例使用的锁默认的是this对象作为锁,所以它们使用的是同一把锁争抢的是同一把锁的时候必然要等待只有一条线程可以持有锁。一条线程执行完成后才可以执行另一条线程。

2、当两个线程访问的是两个对象的同步方法。

	static SynchronizedObectMethod3 intance=new SynchronizedObectMethod3();
    static SynchronizedObectMethod3 intance2=new SynchronizedObectMethod3();
	public static void main(String[] args) {
		Thread th1=new Thread(intance);
		Thread th2=new Thread(intance2);
		th1.start();
		th2.start();
		while(th1.isAlive() || th2.isAlive()){
			
		}
		System.out.println("finished");
	}
	public void run() {
		method();
	}
	public  synchronized void method(){
		System.out.println("我是对象锁的方法修饰符形式,我叫:"+Thread.currentThread().getName());
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"结束");
	}

执行结果:两个线程同时执行同时结束。它们是两个不同的实例,虽然都是this对象但是不是指的同一个对象。

3、两条线程访问的是synchronize的静态的方法。

这种情况上次有类似的例子(类锁的static形式):https://mp.csdn.net/postedit/85791038

static SynchronizedClassStatic4 instance1 = new SynchronizedClassStatic4();
	static SynchronizedClassStatic4 instance2 = new SynchronizedClassStatic4();

	public static void main(String[] args) {
		Thread th1 = new Thread(instance1);
		Thread th2 = new Thread(instance2);
		th1.start();
		th2.start();
		while (th1.isAlive() || th2.isAlive()) {

		}
		System.out.println("finished");
	}

	public void run() {
		method();
	}

	public static synchronized void method() {
		System.out.println("我是类锁的第一种形式,static形式,我叫:" + Thread.currentThread().getName());
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName() + "结束");
	}

执行结果:先是第一条执行,执行完后再执行第二条。虽然有两个不同的实例但是使用了static修饰了就指向同一个对象。

4、同时访问同步方法与非同步方法。

package com.zy.san.synSan;
/**
 * 
 * 
 * @author Administrator
 *同时访问同步方法与非同步方法
 */
public class SynchronizedYesAntNo6 implements Runnable{
	static SynchronizedYesAntNo6 instance=new SynchronizedYesAntNo6();
	
	public static void main(String[] args) {
		Thread th1=new Thread(instance);
		Thread th2=new Thread(instance);
		th1.start();
		th2.start();
		while(th1.isAlive()||th2.isAlive()){
			
		}
		System.out.println("finished");
	}
	
	@Override
	public void run() {
		if(Thread.currentThread().getName().equals("Thread-0")){
			method1();
		}else{
			method2();
		}
		
	}
	public synchronized void method1(){
		System.out.println("我是加了同步的方法"+Thread.currentThread().getName());
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"结束");
		
	}
	public synchronized static void method2(){
		System.out.println("我是没加了同步的方法"+Thread.currentThread().getName());
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"结束");
		
	}
}

执行结果:

结论:synchronize关键字它只作用于指定的方法中,没有指定的是不会干扰的。

5、同时访问同一个类的不同的不同同步方法

package com.zy.san.synSan;

/**
 * 
 * @author Administrator 同时访问同一个类的不同的不同同步方法
 */
public class SynchronizeDifferentMethod6 implements Runnable {
	static SynchronizeDifferentMethod6 instance = new SynchronizeDifferentMethod6();

	public static void main(String[] args) {
		Thread th1 = new Thread(instance);
		Thread th2 = new Thread(instance);
		th1.start();
		th2.start();
		while (th1.isAlive() || th2.isAlive()) {

		}
		System.out.println("finished");
	}

	public void run() {
		method();
		method2();

	}

	private synchronized void method2() {
		System.out.println("我是普通的同步的方法2" + Thread.currentThread().getName());
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName() + "结束");

	}

	private synchronized void method() {
		System.out.println("我是普通的同步的方法1" + Thread.currentThread().getName());
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName() + "结束");

	}

}

运行结果:

结论:虽然synchronize没有明确指定锁对象但是背后的执行逻辑是this对象的。作为同一个实例来讲两个方法是拿到同一个锁。所以是串运行的。

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值