class B_Factory
{
List<B> bs;
}class B
{
C c1;
C c2;
}class C
{
}class D
{
void f()
{
从A取出B对象,调用B对象的方法去修改c1,c2
同时还有对B_Factory.bs的增加删除操作
}
}4个类的关系如代码所示意。多线程环境下,D.f()被并发调用。由于B对象是被C对象共享的(2对1),需要在f()加锁。但问题在于,如果在f()里加锁,那么意味着即便可以并发的线程也将被阻塞(比如A.bs里有2个B对象,第一个B对象对应2个C对象,第二个B对象对应另外2个C对象,4个C对象不同。那么当f()操纵的是第一个B对象时,第二的B对象的f()操作完全可以被并发执行,无需等待第一个B对象的操作完成)我想到的办法是把f()移到B类里去实现,但从代码的角度不太现实,f()里有对B_Factory.bs的增加删除操作,移入B会很麻烦。
或者把f()移到B_Factory,但这和在f()里加锁是一样的,同一时刻,只有一个B对象被操作,即便后面被阻塞的C和现在正在被操作的B完全没关系,也得等着。从java提供的机制看,似乎只有把f()移入B才能解决问题?

解决方案 »

  1.   

    可以用显示的锁ReentranLock和ReentrantReadWriteLock
      

  2.   

    有一件事我不太清楚
    class D
    {
    B b;
    synchronized void f()
    {
    从A取出B对象,调用B对象的方法去修改c1,c2
    同时还有对B_Factory.bs的增加删除操作
    }
    }synchronized 或 ReentrantLock 锁住的是b对象还是B类的所有对象?如果仅仅锁住的是b对象,那么只会阻塞那些和当前获得锁的D.b相同的D对象。
      

  3.   

    你那样锁住的是D对象,实例方法上锁住的是this对象
      

  4.   

    我明白了,在B里加入一个LOCK对象,让D.f()获取此lock对象,然后锁住即可