0

我需要一些帮助来确保我理解同步块。假设以下示例:

public class ThreadStarter {
    public static void main(String[] args) {

        Queue queueObject = new Queue();

        ThreadA thread1 = new ThreadA(queueObject);
        ThreadA thread2 = new ThreadA(queueObject);

        ThreadB thread3 = new ThreadB(queueObject);
        ThreadB thread4 = new ThreadB(queueObject);

        thread1.start();
        thread2.start();

    }
}

public class Queue {

    Object[] the theQueue;

    public Queue(int size){
        theQueue = new Object[size];
    }

    public submitObject(Object o){
        /* add Object to the queue */
    }

    public deleteObject(int objectId){
        /*delete Object from the queue */
    }
}

public class ThreadA extends Thread {

    private Queue queue;

    public ThreadA(Queue queue){
        this.queue = queue;
    }

    public void run() {
        while(!isInterrupted()){
            synchronized(queue) {
                Object o = new Object
                queue.submitObject(o);
                 /* do some other stuff */
        }

        try {
            sleep((int)(Math.random()*1000));
        } catch (interruptedException) {
            Thread.currentThread().interrupt;
        }

            synchronized(queue) {
                 /* do some other stuff on the queue */
            }
        }
    }
}

public class ThreadB extends Thread {

    private Queue queue;

    public ThreadB(Queue queue){
        this.queue = queue;
    }

    public void run() {
        while(!isInterrupted()){
            synchronized(queue) {
                queue.deleteObject(o);
                /* do some other stuff */
        }

        try {
            sleep(1000);
        } catch (interruptedException) {
            Thread.currentThread().interrupt;
        }
    }
}
}

我的问题是,为了安全起见,是否足以同步 ThreadA 中的整个队列对象以将对象提交给队列类?我在 ThreadB 中做了同样的事情来从队列中删除一个对象。或者我是否也必须同步 Queue 类中的 submitObject() 和 deleteObject() 方法?

据我了解,如果我将整个 Queue 类锁定在线程中,如上所示,我应该是安全的 - 对吧?

GreetZ 并提前致谢。

4

3 回答 3

2

您需要做的就是确保没有两个线程不能同时进入 submitObject 和 deleteObjecct。为此,只需将这些方法声明为同步。在这种情况下,类之间共享的队列对象将阻止 2 个线程在它同步的块上蜂拥而至。

此外,如果您想拥有某种阻塞机制,例如:

“如果一个线程想要删除一个对象,如果队列中没有这样的对象,它就必须等待。”

那么您需要做的不仅仅是以这种方式同步:这两个方法仍然应该同步,但是应该使用队列中的 this.wait 停止进入 deleteObject 的线程,直到一个对象变得可用:

public synchronized deleteObject() {
  while( isEmpty() ) {
    try {
      wait();
    } catch( Exception ex ) {
      ex.printStackTrace();
    }//catch
  }//while

  //actually do delete object.
  ...
}//met

然后 submitObject 应该通过执行以下操作通知处于等待状态的线程:

public synchronized submitObject() {
  //do put object
  ...
  notifyAll();
}//met

您还可以跨角色并在这两种方法中添加一些代码,例如,如果队列已满,则允许阻止提交者,并在队列中剩余空间时通知提交者。

于 2012-03-12T19:48:15.590 回答
1

我会在submitObjectdeleteObject方法中同步队列对象,这应该足够了,这意味着:

public submitObject(Object o){
    synchronized (theQueue) {
        ...
    }
}

public deleteObject(int objectId){
    synchronized (theQueue) {
        ...
    }
}
于 2012-03-12T19:40:21.687 回答
1

您所做的相当于同步方法(public synchronized method()this您的queue局部变量同步),除了您必须记住每次使用队列时都需要这样做。同步提交和删除方法会更安全......它也会Object o = new Object()从同步块中删除。

于 2012-03-12T19:40:43.547 回答