一个问题,有简单的类如下,有一个静态synchronized方法,两个非静态synchronized方法,这个类的两个对象(实例):A,B,那么以下几种情况中,那种组合的方法执行会发生互斥(锁竞争)?
1、SyncTest.method1,A.method1;2、A.method2, B.method2;3、SyncTest.method1,A.method2;4、A.method2,A.method3
类示例代码如下:
public class SyncTest {
public synchronized static void method1(String name){
System.out.println(name+" is running method1 start");
try{
Thread.sleep(2000);
}catch (InterruptedException e){
}
System.out.println(name+" is running method1 end");
}
public synchronized void method2(String name){
System.out.println(name+" is running method2 start");
try{
Thread.sleep(2000);
}catch (InterruptedException e){
}
System.out.println(name+" is running method2 end");
}
public synchronized void method3(String name){
System.out.println(name+" is running method3 start");
try{
Thread.sleep(2000);
}catch (InterruptedException e){
}
System.out.println(name+" is running method3 end");
}
}
先说结果:
发生互斥情况的组合为: 1、SyncTest.method1,A.method1;4、A.method2,A.method3
不互斥的情况为:2、A.method2, B.method2;3、SyncTest.method1,A.method2;
其实也并不复杂,了解synchronize的作用域这个问题就很清晰了、
1、synchronized修饰静态方法时,锁是类锁(.class)。这个范围就比对象锁大。这里就算是不同对象,但是只要是该类的对象,就使用的是同一把锁。多个线程调用该类的同步的静态方法时,都会阻塞。所以 1 成立
2、synchronized修饰普通方法时,锁是对象锁(this)。
当该类中有多个普通方法被synchronized修饰(同步),那么这些方法的锁都是这个类的一个对象this。多个线程访问这些方法时,如果这些线程调用方法时使用的是同一个该类的对象,虽然他们访问不同方法,但是他们使用同一个对象来调用,那么这些方法的锁就是一样的,就是这个对象,那么会造成阻塞。如果多个线程通过不同的对象来调用方法(一般都是通过同一个对象访问),那么他们的锁就是不一样的,不会造成阻塞。
所以4 是使用一个对象中的两个synchronized方法,执行时都锁当前对象,导致出现竞争。
用于验证的执行代码示例如下:
package com.java.learn.mine.basic.lock.synchronizetest;
public class SyncTest {
public synchronized static void method1(String name){
System.out.println(name+" is running method1 start");
try{
Thread.sleep(2000);
}catch (InterruptedException e){
}
System.out.println(name+" is running method1 end");
}
public synchronized void method2(String name){
System.out.println(name+" is running method2 start");
try{
Thread.sleep(2000);
}catch (InterruptedException e){
}
System.out.println(name+" is running method2 end");
}
public synchronized void method3(String name){
System.out.println(name+" is running method3 start");
try{
Thread.sleep(2000);
}catch (InterruptedException e){
}
System.out.println(name+" is running method3 end");
}
public static void main(String[] args){
SyncTest syncTest = new SyncTest();
// SyncTest syncTestA2 = new SyncTest();
Thread threadA = new ThreadA(syncTest);
Thread threadB = new ThreadB(syncTest);
threadA.start();
threadB.start();
}
}
class ThreadA extends Thread{
private SyncTest syncTest;
public ThreadA(SyncTest syncTest){
this.syncTest = syncTest;
}
@Override
public void run(){
// SyncTest.method1("ThreadA");
// SyncTest syncTest = new SyncTest();
// syncTest.method2("ThreadA");
// syncTest.method2(ThreadA.class.getName());
SyncTest.method1(ThreadA.class.getName());
}
}
class ThreadB extends Thread{
private SyncTest syncTest;
public ThreadB(SyncTest syncTest){
this.syncTest = syncTest;
}
@Override
public void run(){
// SyncTest syncTest = new SyncTest();
// SyncTest.method1("ThreadB");
// syncTest.method1("ThreadB");
// syncTest.method2(ThreadB.class.getName());
syncTest.method3(ThreadB.class.getName());
}
}
执行后,可以通过打印信息中的start、end来判定两个线程是否同时开始执行方法;进而确定是否发生了锁竞争