synchronized锁相关问题

(1)同一个类中的synchronized method m1和method m2互斥吗?

public class T {

    public static void main(String[] args){
        T t = new T();
        new Thread(t::m1,"t1").start();
        new Thread(t::m2,"t1").start();
    }

    // synchronized加在非静态方法上,锁对象即为this
    public synchronized void m1(){
        System.out.println(Thread.currentThread().getName()+"   m1 start.........");
        try {
            Thread.sleep(100000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"   m1 end.........");
    }

    public void m2(){
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"   m2");
    }
}

t1线程执行m1方法时要去读this对象锁,但是t2线程并不需要读锁,两者各管各的,没有交集(不共用一把锁)。

synchronized锁相关问题_第1张图片

(2)同一个类中的synchronized method m1可以调用synchronized method m2吗?

public class T {

    public synchronized void m1(){
        System.out.println("m1 start");
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        m2();
    }

    public synchronized void m2(){
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("m2");
    }
}

一个同步方法可以调用另一个同步方法,一个线程已经拥有某个对象的锁,再次申请的时候仍然会得到该对象的锁,也就是说synchronized获得的锁是可重入的。可以粗浅地理解为同一个线程在已经持有该锁的情况下,可以再次获取锁,并且会在某个状态量上做+1操作。

synchronized锁相关问题_第2张图片

(3)子类同步方法synchronized method m可以调用父类的synchronized method m吗?

public class T {

    synchronized void m(){
        System.out.println("m start");
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("m end");
    }
}

class TT extends T{

    @Override
    synchronized void m(){
        System.out.println("child m start");
        super.m();
        System.out.println("child m end");
    }
}

子类对象初始化前,会调用父类构造方法,在结构上相当于包裹了一个父类对象,锁对象都是this,而synchronized又是可重入锁,所以是可以的。

synchronized锁相关问题_第3张图片

(4)静态同步方法和非静态同步方法互斥吗?

synchronized锁相关问题_第4张图片

各玩各的,不是同一把锁,谈不上互斥。

(5)带有类锁的方法会影响没有上锁的方法的执行吗?

public class SynchronizedTest {

    public static synchronized void test1() {
        int i = 5;
        while (i-- > 0) {
            System.out.println(Thread.currentThread().getName() + " : " + i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException ie) {
            }
        }
    }

    public void test2() {
        int i = 15;
        while (i-- > 10) {
            System.out.println(Thread.currentThread().getName() + " : " + i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException ie) {
            }
        }
    }

    public static void main(String[] args) {
        final SynchronizedTest myt = new SynchronizedTest();
        Thread test1 = new Thread(new Runnable() {
            public void run() {
                SynchronizedTest.test1();
                myt.test2();
            }
        }, "test1");

        Thread test2 = new Thread(new Runnable() {
            public void run() {
                SynchronizedTest.test1();
                myt.test2();
            }
        }, "test2");
        test1.start();
        test2.start();
    }
}

输出:

test1 : 4
test1 : 3
test1 : 2
test1 : 1
test1 : 0
test2 : 4
test1 : 14
test1 : 13
test2 : 3
test1 : 12
test2 : 2
test1 : 11
test2 : 1
test2 : 0
test1 : 10
test2 : 14
test2 : 13
test2 : 12
test2 : 11
test2 : 10

test1有类锁,所以需要thread1执行完thread2才能执行。thread1执行完test1之后,thread2开始执行test1,在这期间,thread1照常执行test2。也就是说:

  • 类锁只能在同一时刻被一个对象拥有。
  • 当某个方法被类锁锁定的时候,不影响其他对象执行该类中的其他方法。

你可能感兴趣的:(synchronized锁相关问题)