synchronized关键字修饰方法时锁的问题

1.synchronized关键字修饰方法时,多线程访问被修饰的方法:

1.1 一个类,里面有两个方法A,B,都用Synchronized修饰了。当一个线程调用这个类的对象的A方法时候,另一个线程能调用该对象的B方法吗?

测试代码如下:

public class Test {
    
    public static String TEMPLET_FILE = "report/custCare/ReturnReceipt.jasper";

    public static void main(String[] args) throws BaseAppException, InterruptedException {
        TestSyn testSyn = new Test.TestSyn();
        Thread t1 = new Thread(()->{
            testSyn.A();
        });
        Thread t2 = new Thread(()->{
            testSyn.B();
        });
        t1.start();
        t2.start();
    }
    
    static class TestSyn {
        public synchronized void A() {
            try {
                System.out.println("before A " + Thread.currentThread().getName());
                Thread.sleep(10000);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("after A " + Thread.currentThread().getName());
        }
        
        public synchronized void B() {
            try {
                System.out.println("before B " + Thread.currentThread().getName());
                Thread.sleep(10000);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("after B " + Thread.currentThread().getName());
        }
        
        public TestSyn getIncetance() {
            return new TestSyn();
        }
    }
}

运行结果:

before A Thread-0
after A Thread-0
before B Thread-1
after B Thread-1

在Thread-0开始执行方法A 打印before A Thread-0之后等待了10s,线程Thread-1在此期间处于阻塞状态

通过jstack查看jvm堆栈信息可以看出:当Thread-0 sleep 10s处于TIMED_WAITING状态时,Thread-1处于BLOCKED状态

当这种情况,Thread-1需要等待Thread-0执行完A释放锁,然后Thread-1获得锁之后才能执行B。

 

1.2 一个类,里面有两个方法A,B,其中B是静态方法,都用synchronized修饰了。当一个线程调用这个类的对象的A方法时候,另一个线程能调用该类的B方法吗?

测试代码如下

public class Test {
    
    public static String TEMPLET_FILE = "report/custCare/ReturnReceipt.jasper";

    public static void main(String[] args) throws BaseAppException, InterruptedException {
        TestSyn testSyn = new Test.TestSyn();
        Thread t1 = new Thread(()->{
            testSyn.A();
        });
        Thread t2 = new Thread(()->{
            Test.TestSyn.B();
        });
        t1.start();
        t2.start();
    }
    
    static class TestSyn {
        public synchronized void A() {
            try {
                System.out.println("before A " + Thread.currentThread().getName());
                Thread.sleep(10000);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("after A " + Thread.currentThread().getName());
        }
        
        public synchronized static void B() {
            try {
                System.out.println("before B " + Thread.currentThread().getName());
                Thread.sleep(10000);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("after B " + Thread.currentThread().getName());
        }
        
        public TestSyn getIncetance() {
            return new TestSyn();
        }
    }
}

代码运行结果:

before B Thread-1
before A Thread-0
after A Thread-0
after B Thread-1

表示线程Thread-1调用方法B时,线程Thread-0开始调用方法A,不需要等待Thread-1释放锁。可以并发执行。

 

1.3 一个类,里面有两个方法A,B,其中A,B都是静态方法,都用Synchronized修饰了。当一个线程调用这个类的A方法时候,另一个线程能调用该类的B方法吗?

测试代码如下:

public class Test {
    
    public static String TEMPLET_FILE = "report/custCare/ReturnReceipt.jasper";

    public static void main(String[] args) throws BaseAppException, InterruptedException {
        //TestSyn testSyn = new Test.TestSyn();
        Thread t1 = new Thread(()->{
            Test.TestSyn.A();
        });
        Thread t2 = new Thread(()->{
            Test.TestSyn.B();
        });
        t1.start();
        t2.start();
    }
    
    static class TestSyn {
        public synchronized static void A() {
            try {
                System.out.println("before A " + Thread.currentThread().getName());
                Thread.sleep(10000);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("after A " + Thread.currentThread().getName());
        }
        
        public synchronized static void B() {
            try {
                System.out.println("before B " + Thread.currentThread().getName());
                Thread.sleep(10000);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("after B " + Thread.currentThread().getName());
        }
        
        public TestSyn getIncetance() {
            return new TestSyn();
        }
    } 
}

运行结果:

before A Thread-0
after A Thread-0
before B Thread-1
after B Thread-1

在Thread-0开始执行方法A 打印before A Thread-0之后等待了10s,线程Thread-1在此期间处于阻塞状态

通过jstack查看jvm堆栈信息可以看出:当Thread-0 sleep 10s处于TIMED_WAITING状态时,Thread-1处于BLOCKED状态

D:\LDT-Orange\eclipse_oxygen\workspace\workspace_crm_v81c\java\practice\target\classes\com\test\yjw\practice>jps
10704 QuorumPeerMain
22576 Bootstrap
5536 Main
14456
20008 Jps
10908
22716 Test
6108

D:\LDT-Orange\eclipse_oxygen\workspace\workspace_crm_v81c\java\practice\target\classes\com\test\yjw\practice>jstack 22716
2019-12-26 20:40:18
Full thread dump OpenJDK 64-Bit Server VM (25.151-b12 mixed mode):

"DestroyJavaVM" #11 prio=5 os_prio=0 tid=0x00000000035e1060 nid=0x37e4 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Thread-1" #10 prio=5 os_prio=0 tid=0x000000001ba5aab0 nid=0x3700 waiting for monitor entry [0x000000001bf7f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.test.yjw.practice.Test$TestSyn.B(Test.java:71)
        - waiting to lock <0x0000000780bcf448> (a java.lang.Class for com.test.yjw.practice.Test$TestSyn)
        at com.test.yjw.practice.Test.lambda$1(Test.java:51)
        at com.test.yjw.practice.Test$$Lambda$2/455659002.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)

"Thread-0" #9 prio=5 os_prio=0 tid=0x000000001ba58da0 nid=0x3f34 waiting on condition [0x000000001be7f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at com.test.yjw.practice.Test$TestSyn.A(Test.java:61)
        - locked <0x0000000780bcf448> (a java.lang.Class for com.test.yjw.practice.Test$TestSyn)
        at com.test.yjw.practice.Test.lambda$0(Test.java:48)
        at com.test.yjw.practice.Test$$Lambda$1/1406718218.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)

"Service Thread" #8 daemon prio=9 os_prio=0 tid=0x000000001b7a3600 nid=0x5a64 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread1" #7 daemon prio=9 os_prio=2 tid=0x000000001a663b00 nid=0x2578 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x000000001a660530 nid=0x4770 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001a65f450 nid=0x3498 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001a66e250 nid=0x6c34 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

所以,当这种情况,Thread-1需要等待Thread-0执行完A释放锁,然后Thread-1获得锁之后才能执行B

 

总结:

1.当synchronized关键字修饰一个非静态方法时,要执行该方法需要获取相应的对象锁,同一个类中synchronized修饰的不同方法,对象锁是同一个。因此 当不同线程,用同一个对象调用同一个类中synchronized修饰的不同方法时,需要等待一个线程调用完方法释放锁之后,其他线程才有机会能获得锁并执行synchronized修饰的方法。

2.当synchronized关键字修饰一个静态方法时,要执行该方法需要获取相应的对象锁,但静态方法的锁是class对象锁,与实例对象锁不同,因此在一个线程获得实例对象锁的情况下,另一个线程仍可以获得class对象锁。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值