同步方法允许同时进行两次访问

时间:2015-08-20 19:35:05

标签: java multithreading

我有以下方法

public synchronized void run() 
    {

while (done.get()!=true) {

        System.out.println(">>> Golfer #"+ myID + " trying to fill bucket with "+getBallsPerBucket()+" balls.");
        golferBucket = sharedStash.getBucketBalls();
                    if(golferBucket.length == 0){
                        try {
                            sleep(1000);
                        } catch (InterruptedException ex) {
                            Logger.getLogger(Golfer.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
        System.out.println("<<< Golfer #"+ myID + " filled bucket with "+getBallsPerBucket()+" balls, size = "+sharedStash.getSizeStash());

使用此同步方法:

   public synchronized golfBall[] getBucketBalls() {

    golfBall[] bucket = new golfBall[sizeBucket];
    if (getSizeStash().intValue() >= sizeBucket) {

        for (int i = 0; i < sizeBucket; i++) {
            bucket[i] = stash.poll();
        }
        sizeStash.set(sizeStash.intValue() - sizeBucket);
        System.out.println("minusing");
        return bucket;
    }

    return new golfBall[0];

}

然而,当我经营两个不同的高尔夫球手时,线程,它允许两个线程同时访问getBucketBalls()方法。我不知道如何解决这个问题,因为我认为当一个线程获得锁定时,同步来自其他线程的方法锁定访问。另外我在另一篇文章中读到锁对实例有效,但我只有一个BallStash实例,这是getBucketBalls()方法所在的位置。

我得到的输出是:

 =======   River Club Driving Range Open  ========
 ======= Golfers:5 balls: 20 bucketSize:5  ======
 >>> Golfer #1 trying to fill bucket with 5 balls.
 >>> Golfer #2 trying to fill bucket with 5 balls.
 minusing
 minusing
 <<< Golfer #2 filled bucket with 5 balls, size = 10
 <<< Golfer #1 filled bucket with 5 balls, size = 10

请帮忙。感谢。

1 个答案:

答案 0 :(得分:0)

您现有的方法无法奏效。在评论中,您声明您的方法属于不同的类别。

如果两个方法在不同的类中,则在方法定义中使用synchronized关键字不会有帮助。在方法定义中使用时,synchronized类似于在类定义上进行同步。

此:

public class MyClass{
  public synchronized void aMethod(){
    // do stuff
  }
}

等同于:

public class MyClass{
  public void aMethod(){
    synchronized(this){
       // do stuff
    }
  }
}

这意味着你的run()方法和你的getBucketBalls()没有使用相同的对象来控制访问。如果他们没有在同一件事上同步,那么没有什么能阻止他们同时运行。

如果要同步两个不同类中的方法,则需要创建一个可以用作锁的Object,例如:

Object lockObj = new Object();

public void aMethod(){
  synchronized(lockObj){
    // do stuff
  }
}

lockObj可以是任何对象,因此在您的情况下,您可以

public void run(){
  synchronized(ballStash){
     // do work
  }
} 

public void getBucketBalls(){
  synchronized(ballStash){
    // do work
  }
}