前言:多线程是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对象的。作为同一个实例来讲两个方法是拿到同一个锁。所以是串运行的。