场景二:synchronized修饰方法

  相对于场景一:synchronized包裹代码块,synchronized修饰方法的场景要简单明朗许多。因为无论被修饰的方法是静态还是成员,线程访问它时它都只能指定特定的锁。
  而不像synchronized包裹代码块场景下,类A的对象a即可以指定自己为锁,也可以指定类B的对象b为锁,也可以指定类A对应的Class对象为锁,也可以指定类B对应的Class对象为锁……简直生活不能自理 (~﹏~)

假设:有类A,类A对象a,类A同步成员方法 methodMember(),类A同步静态方法 methodStatic();
先上结论:a.当线程需要进入对象a同步成员方法methodMember()时,必须且只能申请methodMember()对应的对象(也即是对象a)作为对象锁。
b.当线程需要进入类A同步静态方法methodStatic()时,必须且只能申请methodStatic()对应的类(也即是类A)作为类锁。


一、修饰成员方法

  一个线程访问synchronized修饰的成员方法,并成功取得对应的对象a作为锁。随后的线程想要进入
    1)同对象的其他同步成员方法;(现象一)
    2)所有以对象a作为对象锁的同步代码块,无论是否同对象、是否同类、是否处于静态方法(现象二)
  时,均会发生竞争。


a.验证现象一
SynchronizedVerify类添加如下main():

public static void main(String[] args){
    final SynchronizedVerify sv = new SynchronizedVerify();

    new Thread(){//定为线程一
        public void run() { sv.methodStyle(); };
    }.start();
    new Thread(){//定为线程二
        public void run() {  sv.methodNormal(); };
    }.start();
}


sv.methodStyle() + sv.methodNormal()输出(无竞争):
methodStyle:0   |Thread-0
methodNormal:0  |Thread-1
methodNormal:1  |Thread-1
methodStyle:1   |Thread-0
methodNormal:2  |Thread-1
methodStyle:2   |Thread-0


将线程二调用的方法改为methodContrast()
sv.methodStyle() + sv.methodContrast()输出(竞争):
methodStyle:0   |Thread-0
methodStyle:1   |Thread-0
methodStyle:2   |Thread-0
methodContrast:0    |Thread-1
methodContrast:1    |Thread-1
methodContrast:2    |Thread-1

b.验证现象二
SynchronizedVerify类添加如下main():

public static void main(String[] args){
    final SynchronizedVerify sv = new SynchronizedVerify();

    new Thread(){//定为线程一
        public void run() { sv.methodStyle(); };
    }.start();
    new Thread(){//定为线程二
        public void run() { sv.blockDiffObj(); };
    }.start();
}


sv.methodStyle() + sv.blockDiffObj()输出(无竞争):
methodStyle:0   |Thread-0
blockDiffObj:0  |Thread-1
methodStyle:1   |Thread-0
blockDiffObj:1  |Thread-1
methodStyle:2   |Thread-0
blockDiffObj:2  |Thread-1


线程二调用方法改为:blockOneself()
sv.methodStyle() + sv.blockOneself()输出(竞争):
methodStyle:0   |Thread-0
methodStyle:1   |Thread-0
methodStyle:2   |Thread-0
blockOneself:0  |Thread-1
blockOneself:1  |Thread-1
blockOneself:2  |Thread-1

其他情况原理类似,不再累述。


二、修饰静态方法

  一个线程访问synchronized修饰的静态方法,并成功取得对应的类A作为锁。随后的线程想要进入
    1)同对象的其他同步静态方法;(现象三)
    2)所有以类A作为类锁的同步代码块,无论是否同对象、是否同类、是否处于静态方法(现象四)
  时,均会发生竞争。


a.验证现象三
SynchronizedVerify类添加如下main():

public static void main(String[] args){
    new Thread(){//定为线程一
        public void run() { SynchronizedVerify.methodStatic(); };
    }.start();
    new Thread(){//定为线程二
        public void run() {  SynchronizedVerify.methodStaticNormal(); };
    }.start();
}


SynchronizedVerify.methodStatic() + SynchronizedVerify.methodStaticNormal()输出(无竞争):
methodStatic:0  |Thread-0
methodStaticNormal:0    |Thread-1
methodStaticNormal:1    |Thread-1
methodStatic:1  |Thread-0
methodStatic:2  |Thread-0
methodStaticNormal:2    |Thread-1



将线程二调用的方法改为methodStaticContrast()
SynchronizedVerify.methodStatic() + SynchronizedVerify.methodStaticContrast()输出(竞争):
methodStatic:0  |Thread-0
methodStatic:1  |Thread-0
methodStatic:2  |Thread-0
methodStaticContrast:0  |Thread-1
methodStaticContrast:1  |Thread-1
methodStaticContrast:2  |Thread-1

b.验证现象四
SynchronizedVerify类添加如下main():

public static void main(String[] args){
    final SynchronizedVerify sv = new SynchronizedVerify();

    new Thread(){//定为线程一
        public void run() { SynchronizedVerify.methodStatic(); };
    }.start();
    new Thread(){//定为线程二
        public void run() { sv.blockOneself(); };
    }.start();
}


SynchronizedVerify.methodStatic() + sv.blockOneself()输出(无竞争):
methodStatic:0  |Thread-0
blockOneself:0  |Thread-1
methodStatic:1  |Thread-0
blockOneself:1  |Thread-1
methodStatic:2  |Thread-0
blockOneself:2  |Thread-1



线程二调用方法改为:blockClass()
SynchronizedVerify.methodStatic() + sv.blockClass()输出(竞争):
methodStatic:0  |Thread-0
methodStatic:1  |Thread-0
methodStatic:2  |Thread-0
blockClass:0    |Thread-1
blockClass:1    |Thread-1
blockClass:2    |Thread-1

其他情况原理类似,不再累述。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值