synchronized&synchronized(something)与对象锁

      Java中同步机制可以用synchronized关键字来实现,当然了,其他办法也是有的。先从synchronized这个关键字说起吧。

      首先synchronized关键字可以用来修饰对象的方法,对象的方法有静态方法与非静态方法;其次,synchronized可以修饰语句块。使用 synchronized关键字的语句块要先获得synchronized(something)中something所对应的锁,这个 something可能有很多种。

      Java中的每个对象都对应一把锁,并且同时只能有一个线程获得该锁,如任何Object的实例或者其子类的实例都有唯一的锁。类似SomeClass.class的大家估计也经常用到,它也是Object的子类,也拥有唯一的锁。但是相同的线程可以多次获取同一对象的唯一锁。比如说在一个同步方法内调用了另一个同步方法的情况。对于每一把唯一锁都有一个计数器来表明当前锁被持有情况。进入同步方法或者同步块是计数器加1,退出时减1。

      最普通的用法是:

           

[java]   view plain copy print ?
  1. public synchronized void function(){//op}  
 

      此时执行此方法需要获得此方法所属的类的当前实例的锁,也就是说this变量所指代的对象的锁。所以上面的语句和以下语句是等效的:

           

[java]   view plain copy print ?
  1. synchronized(this){//op}   

      假设function是SomeClass的一个方法,

[java]   view plain copy print ?
  1. SomeClass sc = new SomeClass();  
  则多个线程调用sc.function()时同时只能有一个线程执行此方法,因为所有线程都先要获得sc对象所拥有的唯一锁。但是当有多个SomeClass的实例如sc1,sc2,sc3...,此时同一个线程同时调用sc1.function(),sc2.function()...时是互不影响的,因为他们要获得的锁不是同一对象的唯一锁,而是多个对象的多把锁,互不影响。

 

一般银行存取款 : 只有一个sc ,其他的sc1,sc2,sc3 ,都是不同的卡,所以互不影响 。

(生产者消费者问题,一般模拟的都是同一个生产者或者消费者的对象的多线程,其实现实中,多个生产者或消费者应该是不同的对象,银行取款是比较形象的)

 

      还有就是synchronized修饰static方法:

           

[java]   view plain copy print ?
  1. public synchronized static void function(){//op}  
 

      此时要执行该方法需要获得此方法所属的类SomeClass对应的SomeClass.class对象的锁。我们知道每个类如SomeClass对应的都有且只有一个SomeClass.class实例。此时多个线程执行此方法时,都要获得所属类的唯一关联实例SomeClass.class所对应的锁,所以无论何时都只有一个线程可以执行此方法。

 

      在使用synchronized同步块时同同步方法基本一样的效果。同步普通的非静态实例时获得该实例所对应的锁,同步静态实例变量是同同步静态方法一样都需要获得其所属类对应的唯一SomeClass.class实例的锁,即类锁。

在程序中获取类锁
可以尝试用以下方式获取类锁
synchronized (xxx.class) {...}
synchronized (Class.forName("xxx")) {...}
同时获取2类锁
同时获取类锁和对象锁是允许的,并不会产生任何问题,但使用类锁时一定要注意,一旦产生类锁的嵌套获取的话,就会产生死锁,因为每个class在内存中都只能生成一个Class实例对象。

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值