synchronized 的真正含义

@synchronized 锁的永远是对象 ,只针对于对象,只能锁对象,常量等是不能加synchronized,一旦加编译也不会通过

@synchronized 锁对象中的非static 就是锁调用该方法的对象,是整个对象

@synchronized 锁对象中的static 方法就是锁整个类 ,和 synchronized(x.class) 和  锁静态代码块 三者都是一样的 就是锁 类加载器 给这个类 的 对象,记住这个类对象不是我们自己new 这个类的对象,而是 jvm 给这个类加载时用的对象,2这不一样。

@synchronized 锁一个对象中属性的话,这个属性必须也是对象,不能是常量,比如集合等,那synchronized(集合)就和这个对象没什么关系了,因为这个集合虽然是在这个对象里,但是 synchronized 针对的是 对象,是锁住的这个对象,即这个集合对象,所以和这个属性所在的大对象是没什么关系的,也就是说锁 大对象中的某个属性小对象时,那个大对象中的其他属性或者方法都是可以访问的,不受那个锁小对象的影响。

@ 一个对象中的非static 方法被锁住后,该对象的其他的非锁的属性或者方法都仍然是可以访问的。

总结:synchronized 锁的是对象,锁对象和锁对象中方法是一样的都是锁的对象,而且每个对象有且仅有一把锁,这个特点就决定锁只针对 加 synchronized 的代码块而言(有synchronized锁的对象、属性、方法),没synchronized 的对象或者属性、方法都仍然可以调用,因为锁既然能称为锁,只会在想锁东西时才会起作用,一个对象将锁用了,另外一个线程想来拿这个对象锁就拿不到,在前边用锁的线程释放锁前一直处于阻塞状态,这就是锁的特点和作用。打个比方就如果一个大房子里有很多小隔间,这些大隔间就是对象,对象的众多方法就是那些小隔间,对象的属性就是这大房子的一些家具之内的,整个大房子只有一把锁,不管是哪个线程是直接通过锁这个大房子还是通过锁小隔间都只有一个结果就是把这个对象的唯一的一把锁给拿走了,再它把钥匙还回来前,别人都是进步了这个房间的,当然这些都是针对于 synchronized 锁下的代码块而言。

注:既然上边说锁 一个对象 ,那同对象其他的非锁方法或者索性是扔然可以拿到的,那假如军团战中 玩家刷积分 和玩家自己调整得积分 是 2个线程,这个积分是线程共有的,即这个积分涉及 线程不安全的,那我现在 是在 加积分的方法里 给这个积分所在对象此命名为A 加锁,这个锁有用么?因为虽然对象加锁了,但是这个对象里的其他属性和方法只要是非锁的仍然可以访问,也就是其他线程仍然可以调用 A对象中的set积分方法,因为这个set积分方法是 无锁的,那这边锁A是不是起不到什么作用?那我要想保证积分线程安全,那我是不是必须要在set积分上加锁才行,但是如果我仅仅在set积分上加锁,但是 我假如2个线程都要set积分,因为 set积分肯定是先拿到当前积分后+上本次所得积分 得到一个总值才会去set 积分,那我这2个线程都 运行到get积分后,而且2个拿到的当前积分都一样,但都没有执行set积分方法了,现在来执行set积分方法,就算这个set积分方法有锁,其实也没有用,因为我2个线程拿当前积分就已经错了,已经不同步了,所以难道还要在get积分上也加锁,但想想就算都在get和set积分上加锁,这2个方法之间总有间隔,有间隔就会出现不同步,就不能保证积分 不安全,那这个积分怎么办呢?

其实上边锁 那个积分所在对象  A 是可以的,为啥说可以的呢,因为 虽然A中有set积分的方法,但这个方法目前只有在这个统一加积分的方法里调用,此命名为B方法,现在在B方法里加了锁A的代码,因为整个功能积分的改动只有在这个B方法里有改动,也就是说任何线程 要想改积分都是调用这个B方法,那我在这个B方法里将整个A对象给锁住,然后在锁块里先get积分然后set积分就没问题了,因为其他 线程 要想改积分也是调用这个同一个B方法,而B方法里有synchronized 锁A的代码,第一个线程抢到锁A的钥匙时可以执行,其他的线程由于抢不到锁A的钥匙,在执行到synchronized(A) 即也想把A锁住这边是执行不了的,因为它没有钥匙,不能先开锁然后再把A锁起来,所以后来的抢不到钥匙的线程只能等待。

posted @ 2015-05-11 13:42  wzhanke  阅读(905)  评论(0编辑  收藏  举报